@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module)
163163
164164 /* A file path -- this is an offline module */
165165 if (module && strchr (module , '/' ))
166- return machine__findnew_module_map ( host_machine , 0 , module );
166+ return dso__new_map ( module );
167167
168168 if (!module )
169169 module = "kernel" ;
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module)
173173 if (strncmp (pos -> dso -> short_name + 1 , module ,
174174 pos -> dso -> short_name_len - 2 ) == 0 &&
175175 module [pos -> dso -> short_name_len - 2 ] == '\0' ) {
176+ map__get (pos );
176177 return pos ;
177178 }
178179 }
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user)
188189 return kernel_get_module_map (target );
189190}
190191
191- static void put_target_map (struct map * map , bool user )
192- {
193- if (map && user ) {
194- /* Only the user map needs to be released */
195- map__put (map );
196- }
197- }
198-
199-
200192static int convert_exec_to_group (const char * exec , char * * result )
201193{
202194 char * ptr1 , * ptr2 , * exec_copy ;
@@ -267,21 +259,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
267259 return true;
268260}
269261
270- /*
271- * NOTE:
272- * '.gnu.linkonce.this_module' section of kernel module elf directly
273- * maps to 'struct module' from linux/module.h. This section contains
274- * actual module name which will be used by kernel after loading it.
275- * But, we cannot use 'struct module' here since linux/module.h is not
276- * exposed to user-space. Offset of 'name' has remained same from long
277- * time, so hardcoding it here.
278- */
279- #ifdef __LP64__
280- #define MOD_NAME_OFFSET 24
281- #else
282- #define MOD_NAME_OFFSET 12
283- #endif
284-
285262/*
286263 * @module can be module name of module file path. In case of path,
287264 * inspect elf and find out what is actual module name.
@@ -296,6 +273,7 @@ static char *find_module_name(const char *module)
296273 Elf_Data * data ;
297274 Elf_Scn * sec ;
298275 char * mod_name = NULL ;
276+ int name_offset ;
299277
300278 fd = open (module , O_RDONLY );
301279 if (fd < 0 )
@@ -317,7 +295,21 @@ static char *find_module_name(const char *module)
317295 if (!data || !data -> d_buf )
318296 goto ret_err ;
319297
320- mod_name = strdup ((char * )data -> d_buf + MOD_NAME_OFFSET );
298+ /*
299+ * NOTE:
300+ * '.gnu.linkonce.this_module' section of kernel module elf directly
301+ * maps to 'struct module' from linux/module.h. This section contains
302+ * actual module name which will be used by kernel after loading it.
303+ * But, we cannot use 'struct module' here since linux/module.h is not
304+ * exposed to user-space. Offset of 'name' has remained same from long
305+ * time, so hardcoding it here.
306+ */
307+ if (ehdr .e_ident [EI_CLASS ] == ELFCLASS32 )
308+ name_offset = 12 ;
309+ else /* expect ELFCLASS64 by default */
310+ name_offset = 24 ;
311+
312+ mod_name = strdup ((char * )data -> d_buf + name_offset );
321313
322314ret_err :
323315 elf_end (elf );
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
412404 }
413405
414406out :
415- put_target_map (map , uprobes );
407+ map__put (map );
416408 return ret ;
417409
418410}
@@ -618,6 +610,51 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
618610 return ret ? : - ENOENT ;
619611}
620612
613+ /*
614+ * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
615+ * and generate new symbols with suffixes such as .constprop.N or .isra.N
616+ * etc. Since those symbols are not recorded in DWARF, we have to find
617+ * correct generated symbols from offline ELF binary.
618+ * For online kernel or uprobes we don't need this because those are
619+ * rebased on _text, or already a section relative address.
620+ */
621+ static int
622+ post_process_offline_probe_trace_events (struct probe_trace_event * tevs ,
623+ int ntevs , const char * pathname )
624+ {
625+ struct symbol * sym ;
626+ struct map * map ;
627+ unsigned long stext = 0 ;
628+ u64 addr ;
629+ int i ;
630+
631+ /* Prepare a map for offline binary */
632+ map = dso__new_map (pathname );
633+ if (!map || get_text_start_address (pathname , & stext ) < 0 ) {
634+ pr_warning ("Failed to get ELF symbols for %s\n" , pathname );
635+ return - EINVAL ;
636+ }
637+
638+ for (i = 0 ; i < ntevs ; i ++ ) {
639+ addr = tevs [i ].point .address + tevs [i ].point .offset - stext ;
640+ sym = map__find_symbol (map , addr );
641+ if (!sym )
642+ continue ;
643+ if (!strcmp (sym -> name , tevs [i ].point .symbol ))
644+ continue ;
645+ /* If we have no realname, use symbol for it */
646+ if (!tevs [i ].point .realname )
647+ tevs [i ].point .realname = tevs [i ].point .symbol ;
648+ else
649+ free (tevs [i ].point .symbol );
650+ tevs [i ].point .symbol = strdup (sym -> name );
651+ tevs [i ].point .offset = addr - sym -> start ;
652+ }
653+ map__put (map );
654+
655+ return 0 ;
656+ }
657+
621658static int add_exec_to_probe_trace_events (struct probe_trace_event * tevs ,
622659 int ntevs , const char * exec )
623660{
@@ -679,7 +716,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
679716
680717 /* Skip post process if the target is an offline kernel */
681718 if (symbol_conf .ignore_vmlinux_buildid )
682- return 0 ;
719+ return post_process_offline_probe_trace_events (tevs , ntevs ,
720+ symbol_conf .vmlinux_name );
683721
684722 reloc_sym = kernel_get_ref_reloc_sym ();
685723 if (!reloc_sym ) {
@@ -2869,7 +2907,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
28692907 }
28702908
28712909out :
2872- put_target_map (map , pev -> uprobes );
2910+ map__put (map );
28732911 free (syms );
28742912 return ret ;
28752913
@@ -3362,10 +3400,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
33623400 return ret ;
33633401
33643402 /* Get a symbol map */
3365- if (user )
3366- map = dso__new_map (target );
3367- else
3368- map = kernel_get_module_map (target );
3403+ map = get_target_map (target , user );
33693404 if (!map ) {
33703405 pr_err ("Failed to get a map for %s\n" , (target ) ? : "kernel" );
33713406 return - EINVAL ;
@@ -3397,9 +3432,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
33973432 }
33983433
33993434end :
3400- if (user ) {
3401- map__put (map );
3402- }
3435+ map__put (map );
34033436 exit_probe_symbol_maps ();
34043437
34053438 return ret ;
0 commit comments