@@ -9,6 +9,8 @@ use serde::{Deserialize, Serialize};
9
9
use std:: collections:: HashMap ;
10
10
#[ cfg( unix) ]
11
11
use std:: path:: PathBuf ;
12
+ #[ cfg( unix) ]
13
+ use std:: rc:: Rc ;
12
14
13
15
#[ derive( Debug , Clone , PartialEq , Serialize , Deserialize , JsonSchema ) ]
14
16
pub struct ErrorData {
@@ -23,49 +25,69 @@ pub struct ErrorData {
23
25
}
24
26
25
27
#[ cfg( unix) ]
26
- # [ derive ( Default ) ]
27
- pub struct CachedElfResolvers {
28
- elf_resolvers : HashMap < PathBuf , ElfResolver > ,
28
+ pub struct CachedElfResolvers < ' a > {
29
+ symbolizer : & ' a mut blazesym :: symbolize :: Symbolizer ,
30
+ elf_resolvers : HashMap < PathBuf , Rc < ElfResolver > > ,
29
31
}
30
32
31
33
#[ cfg( unix) ]
32
- impl CachedElfResolvers {
33
- pub fn get ( & mut self , file_path : & PathBuf ) -> anyhow:: Result < & ElfResolver > {
34
+ impl < ' a > CachedElfResolvers < ' a > {
35
+ pub fn new ( symbolizer : & ' a mut blazesym:: symbolize:: Symbolizer ) -> Self {
36
+ Self {
37
+ symbolizer,
38
+ elf_resolvers : HashMap :: new ( ) ,
39
+ }
40
+ }
41
+
42
+ pub fn get ( & mut self , file_path : & PathBuf ) -> anyhow:: Result < Rc < ElfResolver > > {
34
43
use anyhow:: Context ;
35
44
if !self . elf_resolvers . contains_key ( file_path. as_path ( ) ) {
36
- let resolver = ElfResolver :: open ( file_path) . with_context ( || {
45
+ let resolver = Rc :: new ( ElfResolver :: open ( file_path) . with_context ( || {
37
46
format ! (
38
47
"ElfResolver::open failed for '{}'" ,
39
48
file_path. to_string_lossy( )
40
49
)
41
- } ) ?;
50
+ } ) ?) ;
51
+ let _ = self
52
+ . symbolizer
53
+ . register_elf_resolver ( file_path. as_path ( ) , Rc :: clone ( & resolver) ) ;
42
54
self . elf_resolvers . insert ( file_path. clone ( ) , resolver) ;
43
55
}
44
56
self . elf_resolvers
45
57
. get ( file_path. as_path ( ) )
46
58
. with_context ( || "key '{}' not found in ElfResolver cache" )
59
+ . cloned ( )
47
60
}
48
61
}
49
62
50
63
#[ cfg( unix) ]
51
64
impl ErrorData {
52
65
pub fn normalize_ips ( & mut self , pid : u32 ) -> anyhow:: Result < ( ) > {
53
- let mut errors = 0 ;
54
- let mut elf_resolvers = CachedElfResolvers :: default ( ) ;
66
+ let mut symbolizer = blazesym :: symbolize :: Symbolizer :: new ( ) ;
67
+ let mut elf_resolvers = CachedElfResolvers :: new ( & mut symbolizer ) ;
55
68
let normalizer = blazesym:: normalize:: Normalizer :: builder ( )
56
69
. enable_vma_caching ( true )
57
70
. enable_build_ids ( true )
58
71
. enable_build_id_caching ( true )
59
72
. build ( ) ;
60
- let pid = pid. into ( ) ;
73
+ self . normalize_ips_impl ( pid, & normalizer, & mut elf_resolvers)
74
+ }
75
+
76
+ pub ( crate ) fn normalize_ips_impl (
77
+ & mut self ,
78
+ pid : u32 ,
79
+ normalizer : & blazesym:: normalize:: Normalizer ,
80
+ elf_resolvers : & mut CachedElfResolvers ,
81
+ ) -> anyhow:: Result < ( ) > {
82
+ let mut errors = 0 ;
61
83
self . stack
62
- . normalize_ips ( & normalizer, pid, & mut elf_resolvers)
84
+ . normalize_ips ( normalizer, pid. into ( ) , elf_resolvers)
63
85
. unwrap_or_else ( |_| errors += 1 ) ;
64
86
65
87
for thread in & mut self . threads {
66
88
thread
67
89
. stack
68
- . normalize_ips ( & normalizer, pid, & mut elf_resolvers)
90
+ . normalize_ips ( normalizer, pid. into ( ) , elf_resolvers)
69
91
. unwrap_or_else ( |_| errors += 1 ) ;
70
92
}
71
93
anyhow:: ensure!(
@@ -75,21 +97,43 @@ impl ErrorData {
75
97
Ok ( ( ) )
76
98
}
77
99
78
- pub fn resolve_names ( & mut self , pid : u32 ) -> anyhow:: Result < ( ) > {
79
- let mut errors = 0 ;
100
+ pub ( crate ) fn create_symbolizer_source < ' a > (
101
+ pid : u32 ,
102
+ ) -> blazesym:: symbolize:: source:: Source < ' a > {
80
103
let mut process = blazesym:: symbolize:: source:: Process :: new ( pid. into ( ) ) ;
81
104
// https://github.com/libbpf/blazesym/issues/518
82
105
process. map_files = false ;
83
- let src = blazesym:: symbolize:: source:: Source :: Process ( process) ;
106
+ blazesym:: symbolize:: source:: Source :: Process ( process)
107
+ }
108
+
109
+ pub ( crate ) fn create_normalizer ( ) -> blazesym:: normalize:: Normalizer {
110
+ blazesym:: normalize:: Normalizer :: builder ( )
111
+ . enable_vma_caching ( true )
112
+ . enable_build_ids ( true )
113
+ . enable_build_id_caching ( true )
114
+ . build ( )
115
+ }
116
+
117
+ pub fn resolve_names ( & mut self , pid : u32 ) -> anyhow:: Result < ( ) > {
118
+ let src = Self :: create_symbolizer_source ( pid) ;
84
119
let symbolizer = blazesym:: symbolize:: Symbolizer :: new ( ) ;
120
+ self . resolve_names_impl ( & symbolizer, & src)
121
+ }
122
+
123
+ pub ( crate ) fn resolve_names_impl (
124
+ & mut self ,
125
+ symbolizer : & blazesym:: symbolize:: Symbolizer ,
126
+ src : & blazesym:: symbolize:: source:: Source ,
127
+ ) -> anyhow:: Result < ( ) > {
128
+ let mut errors = 0 ;
85
129
self . stack
86
- . resolve_names ( & src, & symbolizer)
130
+ . resolve_names ( src, symbolizer)
87
131
. unwrap_or_else ( |_| errors += 1 ) ;
88
132
89
133
for thread in & mut self . threads {
90
134
thread
91
135
. stack
92
- . resolve_names ( & src, & symbolizer)
136
+ . resolve_names ( src, symbolizer)
93
137
. unwrap_or_else ( |_| errors += 1 ) ;
94
138
}
95
139
anyhow:: ensure!(
0 commit comments