1- use crate :: executor:: wall_time:: perf:: perf_map :: ModuleSymbols ;
1+ use crate :: executor:: wall_time:: perf:: module_symbols :: ModuleSymbols ;
22use crate :: prelude:: * ;
33use addr2line:: { fallible_iterator:: FallibleIterator , gimli} ;
44use object:: { Object , ObjectSection } ;
5+ use rayon:: prelude:: * ;
56use runner_shared:: debug_info:: { DebugInfo , ModuleDebugInfo } ;
67use std:: path:: Path ;
78
89type EndianRcSlice = gimli:: EndianRcSlice < gimli:: RunTimeEndian > ;
910
1011pub trait ModuleDebugInfoExt {
11- fn from_symbols < P : AsRef < Path > > ( path : P , symbols : & ModuleSymbols ) -> anyhow:: Result < Self >
12+ fn from_symbols < P : AsRef < Path > > (
13+ path : P ,
14+ symbols : & ModuleSymbols ,
15+ load_bias : u64 ,
16+ ) -> anyhow:: Result < Self >
1217 where
1318 Self : Sized ;
1419
@@ -36,12 +41,15 @@ pub trait ModuleDebugInfoExt {
3641
3742impl ModuleDebugInfoExt for ModuleDebugInfo {
3843 /// Create debug info from existing symbols by looking up file/line in DWARF
39- fn from_symbols < P : AsRef < Path > > ( path : P , symbols : & ModuleSymbols ) -> anyhow:: Result < Self > {
44+ fn from_symbols < P : AsRef < Path > > (
45+ path : P ,
46+ symbols : & ModuleSymbols ,
47+ load_bias : u64 ,
48+ ) -> anyhow:: Result < Self > {
4049 let content = std:: fs:: read ( path. as_ref ( ) ) ?;
4150 let object = object:: File :: parse ( & * content) ?;
4251
4352 let ctx = Self :: create_dwarf_context ( & object) . context ( "Failed to create DWARF context" ) ?;
44- let load_bias = symbols. load_bias ( ) ;
4553 let ( mut min_addr, mut max_addr) = ( None , None ) ;
4654 let debug_infos = symbols
4755 . symbols ( )
@@ -96,34 +104,27 @@ impl ModuleDebugInfoExt for ModuleDebugInfo {
96104 }
97105}
98106
99- /// Represents all the modules inside a process and their debug info.
100- pub struct ProcessDebugInfo {
101- modules : Vec < ModuleDebugInfo > ,
102- }
103-
104- impl ProcessDebugInfo {
105- pub fn new (
106- process_symbols : & crate :: executor:: wall_time:: perf:: perf_map:: ProcessSymbols ,
107- ) -> Self {
108- let mut modules = Vec :: new ( ) ;
109- for ( path, module_symbols) in process_symbols. modules_with_symbols ( ) {
110- match ModuleDebugInfo :: from_symbols ( path, module_symbols) {
111- Ok ( module_debug_info) => {
112- modules. push ( module_debug_info) ;
113- }
107+ /// Compute debug info once per unique ELF path from deduplicated symbols.
108+ /// Returns a map of path -> ModuleDebugInfo with `load_bias: 0` (load bias is per-pid).
109+ pub fn debug_info_by_path (
110+ mounted_modules_by_path : & std:: collections:: HashMap <
111+ std:: path:: PathBuf ,
112+ crate :: executor:: wall_time:: perf:: parse_perf_file:: MountedModule ,
113+ > ,
114+ ) -> std:: collections:: HashMap < std:: path:: PathBuf , ModuleDebugInfo > {
115+ mounted_modules_by_path
116+ . par_iter ( )
117+ . filter_map ( |( path, mounted_module) | {
118+ let module_symbols = mounted_module. module_symbols . as_ref ( ) ?;
119+ match ModuleDebugInfo :: from_symbols ( path, module_symbols, 0 ) {
120+ Ok ( module_debug_info) => Some ( ( path. clone ( ) , module_debug_info) ) ,
114121 Err ( error) => {
115122 trace ! ( "Failed to load debug info for module {path:?}: {error}" ) ;
123+ None
116124 }
117125 }
118- }
119-
120- Self { modules }
121- }
122-
123- /// Returns the debug info modules for this process
124- pub fn modules ( self ) -> Vec < ModuleDebugInfo > {
125- self . modules
126- }
126+ } )
127+ . collect ( )
127128}
128129
129130#[ cfg( test) ]
@@ -134,23 +135,30 @@ mod tests {
134135 fn test_golang_debug_info ( ) {
135136 let ( start_addr, end_addr, file_offset) =
136137 ( 0x0000000000402000_u64 , 0x000000000050f000_u64 , 0x2000 ) ;
137- let module_symbols = ModuleSymbols :: new (
138+ let module_symbols = ModuleSymbols :: from_elf ( "testdata/perf_map/go_fib.bin" ) . unwrap ( ) ;
139+ let load_bias = ModuleSymbols :: compute_load_bias (
138140 "testdata/perf_map/go_fib.bin" ,
139141 start_addr,
140142 end_addr,
141143 file_offset,
142144 )
143145 . unwrap ( ) ;
144- let module_debug_info =
145- ModuleDebugInfo :: from_symbols ( "testdata/perf_map/go_fib.bin" , & module_symbols) . unwrap ( ) ;
146+ let module_debug_info = ModuleDebugInfo :: from_symbols (
147+ "testdata/perf_map/go_fib.bin" ,
148+ & module_symbols,
149+ load_bias,
150+ )
151+ . unwrap ( ) ;
146152 insta:: assert_debug_snapshot!( module_debug_info. debug_infos) ;
147153 }
148154
149155 #[ test]
150156 fn test_cpp_debug_info ( ) {
151157 let ( start_addr, end_addr, file_offset) =
152158 ( 0x0000000000400000_u64 , 0x0000000000459000_u64 , 0x0 ) ;
153- let module_symbols = ModuleSymbols :: new (
159+ let module_symbols =
160+ ModuleSymbols :: from_elf ( "testdata/perf_map/cpp_my_benchmark.bin" ) . unwrap ( ) ;
161+ let load_bias = ModuleSymbols :: compute_load_bias (
154162 "testdata/perf_map/cpp_my_benchmark.bin" ,
155163 start_addr,
156164 end_addr,
@@ -160,6 +168,7 @@ mod tests {
160168 let mut module_debug_info = ModuleDebugInfo :: from_symbols (
161169 "testdata/perf_map/cpp_my_benchmark.bin" ,
162170 & module_symbols,
171+ load_bias,
163172 )
164173 . unwrap ( ) ;
165174
@@ -172,27 +181,33 @@ mod tests {
172181 fn test_rust_divan_debug_info ( ) {
173182 const MODULE_PATH : & str = "testdata/perf_map/divan_sleep_benches.bin" ;
174183
175- let module_symbols =
176- ModuleSymbols :: new ( MODULE_PATH , 0x00005555555a2000 , 0x0000555555692000 , 0x4d000 )
177- . unwrap ( ) ;
184+ let module_symbols = ModuleSymbols :: from_elf ( MODULE_PATH ) . unwrap ( ) ;
185+ let load_bias = ModuleSymbols :: compute_load_bias (
186+ MODULE_PATH ,
187+ 0x00005555555a2000 ,
188+ 0x0000555555692000 ,
189+ 0x4d000 ,
190+ )
191+ . unwrap ( ) ;
178192 let module_debug_info =
179- ModuleDebugInfo :: from_symbols ( MODULE_PATH , & module_symbols) . unwrap ( ) ;
193+ ModuleDebugInfo :: from_symbols ( MODULE_PATH , & module_symbols, load_bias ) . unwrap ( ) ;
180194 insta:: assert_debug_snapshot!( module_debug_info. debug_infos) ;
181195 }
182196
183197 #[ test]
184198 fn test_the_algorithms_debug_info ( ) {
185199 const MODULE_PATH : & str = "testdata/perf_map/the_algorithms.bin" ;
186200
187- let module_symbols = ModuleSymbols :: new (
201+ let module_symbols = ModuleSymbols :: from_elf ( MODULE_PATH ) . unwrap ( ) ;
202+ let load_bias = ModuleSymbols :: compute_load_bias (
188203 MODULE_PATH ,
189204 0x00005573e59fe000 ,
190205 0x00005573e5b07000 ,
191206 0x00052000 ,
192207 )
193208 . unwrap ( ) ;
194209 let module_debug_info =
195- ModuleDebugInfo :: from_symbols ( MODULE_PATH , & module_symbols) . unwrap ( ) ;
210+ ModuleDebugInfo :: from_symbols ( MODULE_PATH , & module_symbols, load_bias ) . unwrap ( ) ;
196211 insta:: assert_debug_snapshot!( module_debug_info. debug_infos) ;
197212 }
198213
@@ -202,10 +217,12 @@ mod tests {
202217
203218 let ( start_addr, end_addr, file_offset) =
204219 ( 0x0000555555e6d000_u64 , 0x0000555556813000_u64 , 0x918000 ) ;
205- let module_symbols =
206- ModuleSymbols :: new ( MODULE_PATH , start_addr, end_addr, file_offset) . unwrap ( ) ;
220+ let module_symbols = ModuleSymbols :: from_elf ( MODULE_PATH ) . unwrap ( ) ;
221+ let load_bias =
222+ ModuleSymbols :: compute_load_bias ( MODULE_PATH , start_addr, end_addr, file_offset)
223+ . unwrap ( ) ;
207224 let module_debug_info =
208- ModuleDebugInfo :: from_symbols ( MODULE_PATH , & module_symbols) . unwrap ( ) ;
225+ ModuleDebugInfo :: from_symbols ( MODULE_PATH , & module_symbols, load_bias ) . unwrap ( ) ;
209226 insta:: assert_debug_snapshot!( module_debug_info. debug_infos) ;
210227 }
211228}
0 commit comments