@@ -130,6 +130,7 @@ struct perf_inject {
130130 struct perf_file_section secs [HEADER_FEAT_BITS ];
131131 struct guest_session guest_session ;
132132 struct strlist * known_build_ids ;
133+ const struct evsel * mmap_evsel ;
133134};
134135
135136struct event_entry {
@@ -138,8 +139,13 @@ struct event_entry {
138139 union perf_event event [];
139140};
140141
141- static int dso__inject_build_id (struct dso * dso , const struct perf_tool * tool ,
142- struct machine * machine , u8 cpumode , u32 flags );
142+ static int tool__inject_build_id (const struct perf_tool * tool ,
143+ struct perf_sample * sample ,
144+ struct machine * machine ,
145+ const struct evsel * evsel ,
146+ __u16 misc ,
147+ const char * filename ,
148+ struct dso * dso , u32 flags );
143149
144150static int output_bytes (struct perf_inject * inject , void * buf , size_t sz )
145151{
@@ -422,6 +428,28 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename,
422428 return dso ;
423429}
424430
431+ /*
432+ * The evsel used for the sample ID for mmap events. Typically stashed when
433+ * processing mmap events. If not stashed, search the evlist for the first mmap
434+ * gathering event.
435+ */
436+ static const struct evsel * inject__mmap_evsel (struct perf_inject * inject )
437+ {
438+ struct evsel * pos ;
439+
440+ if (inject -> mmap_evsel )
441+ return inject -> mmap_evsel ;
442+
443+ evlist__for_each_entry (inject -> session -> evlist , pos ) {
444+ if (pos -> core .attr .mmap ) {
445+ inject -> mmap_evsel = pos ;
446+ return pos ;
447+ }
448+ }
449+ pr_err ("No mmap events found\n" );
450+ return NULL ;
451+ }
452+
425453static int perf_event__repipe_common_mmap (const struct perf_tool * tool ,
426454 union perf_event * event ,
427455 struct perf_sample * sample ,
@@ -469,12 +497,28 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
469497 }
470498
471499 if (dso && !dso__hit (dso )) {
472- dso__set_hit (dso );
473- dso__inject_build_id (dso , tool , machine , sample -> cpumode , flags );
500+ struct evsel * evsel = evlist__event2evsel (inject -> session -> evlist , event );
501+
502+ if (evsel ) {
503+ dso__set_hit (dso );
504+ tool__inject_build_id (tool , sample , machine , evsel ,
505+ /*misc=*/ sample -> cpumode ,
506+ filename , dso , flags );
507+ }
474508 }
475509 } else {
510+ int err ;
511+
512+ /*
513+ * Remember the evsel for lazy build id generation. It is used
514+ * for the sample id header type.
515+ */
516+ if (inject -> build_id_style == BID_RWS__INJECT_HEADER_LAZY &&
517+ !inject -> mmap_evsel )
518+ inject -> mmap_evsel = evlist__event2evsel (inject -> session -> evlist , event );
519+
476520 /* Create the thread, map, etc. Not done for the unordered inject all case. */
477- int err = perf_event_process (tool , event , sample , machine );
521+ err = perf_event_process (tool , event , sample , machine );
478522
479523 if (err ) {
480524 dso__put (dso );
@@ -667,58 +711,95 @@ static bool perf_inject__lookup_known_build_id(struct perf_inject *inject,
667711 return false;
668712}
669713
670- static int dso__inject_build_id (struct dso * dso , const struct perf_tool * tool ,
671- struct machine * machine , u8 cpumode , u32 flags )
714+ static int tool__inject_build_id (const struct perf_tool * tool ,
715+ struct perf_sample * sample ,
716+ struct machine * machine ,
717+ const struct evsel * evsel ,
718+ __u16 misc ,
719+ const char * filename ,
720+ struct dso * dso , u32 flags )
672721{
673- struct perf_inject * inject = container_of (tool , struct perf_inject ,
674- tool );
722+ struct perf_inject * inject = container_of (tool , struct perf_inject , tool );
675723 int err ;
676724
677- if (is_anon_memory (dso__long_name ( dso ) ) || flags & MAP_HUGETLB )
725+ if (is_anon_memory (filename ) || flags & MAP_HUGETLB )
678726 return 0 ;
679- if (is_no_dso_memory (dso__long_name ( dso ) ))
727+ if (is_no_dso_memory (filename ))
680728 return 0 ;
681729
682730 if (inject -> known_build_ids != NULL &&
683731 perf_inject__lookup_known_build_id (inject , dso ))
684732 return 1 ;
685733
686734 if (dso__read_build_id (dso ) < 0 ) {
687- pr_debug ("no build_id found for %s\n" , dso__long_name ( dso ) );
735+ pr_debug ("no build_id found for %s\n" , filename );
688736 return -1 ;
689737 }
690738
691- err = perf_event__synthesize_build_id (tool , dso , cpumode ,
692- perf_event__repipe , machine );
739+ err = perf_event__synthesize_build_id (tool , sample , machine ,
740+ perf_event__repipe ,
741+ evsel , misc , dso__bid (dso ),
742+ filename );
693743 if (err ) {
694- pr_err ("Can't synthesize build_id event for %s\n" , dso__long_name ( dso ) );
744+ pr_err ("Can't synthesize build_id event for %s\n" , filename );
695745 return -1 ;
696746 }
697747
698748 return 0 ;
699749}
700750
751+ static int mark_dso_hit (const struct perf_tool * tool ,
752+ struct perf_sample * sample ,
753+ struct machine * machine ,
754+ const struct evsel * mmap_evsel ,
755+ struct map * map , bool sample_in_dso )
756+ {
757+ struct dso * dso ;
758+ u16 misc = sample -> cpumode ;
759+
760+ if (!map )
761+ return 0 ;
762+
763+ if (!sample_in_dso ) {
764+ u16 guest_mask = PERF_RECORD_MISC_GUEST_KERNEL |
765+ PERF_RECORD_MISC_GUEST_USER ;
766+
767+ if ((misc & guest_mask ) != 0 ) {
768+ misc &= PERF_RECORD_MISC_HYPERVISOR ;
769+ misc |= __map__is_kernel (map )
770+ ? PERF_RECORD_MISC_GUEST_KERNEL
771+ : PERF_RECORD_MISC_GUEST_USER ;
772+ } else {
773+ misc &= PERF_RECORD_MISC_HYPERVISOR ;
774+ misc |= __map__is_kernel (map )
775+ ? PERF_RECORD_MISC_KERNEL
776+ : PERF_RECORD_MISC_USER ;
777+ }
778+ }
779+ dso = map__dso (map );
780+ if (dso && !dso__hit (dso )) {
781+ dso__set_hit (dso );
782+ tool__inject_build_id (tool , sample , machine ,
783+ mmap_evsel , misc , dso__long_name (dso ), dso ,
784+ map__flags (map ));
785+ }
786+ return 0 ;
787+ }
788+
701789struct mark_dso_hit_args {
702790 const struct perf_tool * tool ;
791+ struct perf_sample * sample ;
703792 struct machine * machine ;
704- u8 cpumode ;
793+ const struct evsel * mmap_evsel ;
705794};
706795
707796static int mark_dso_hit_callback (struct callchain_cursor_node * node , void * data )
708797{
709798 struct mark_dso_hit_args * args = data ;
710799 struct map * map = node -> ms .map ;
711800
712- if (map ) {
713- struct dso * dso = map__dso (map );
714-
715- if (dso && !dso__hit (dso )) {
716- dso__set_hit (dso );
717- dso__inject_build_id (dso , args -> tool , args -> machine ,
718- args -> cpumode , map__flags (map ));
719- }
720- }
721- return 0 ;
801+ return mark_dso_hit (args -> tool , args -> sample , args -> machine ,
802+ args -> mmap_evsel , map , /*sample_in_dso=*/ false);
722803}
723804
724805int perf_event__inject_buildid (const struct perf_tool * tool , union perf_event * event ,
@@ -728,10 +809,16 @@ int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *e
728809{
729810 struct addr_location al ;
730811 struct thread * thread ;
812+ struct perf_inject * inject = container_of (tool , struct perf_inject , tool );
731813 struct mark_dso_hit_args args = {
732814 .tool = tool ,
815+ /*
816+ * Use the parsed sample data of the sample event, which will
817+ * have a later timestamp than the mmap event.
818+ */
819+ .sample = sample ,
733820 .machine = machine ,
734- .cpumode = sample -> cpumode ,
821+ .mmap_evsel = inject__mmap_evsel ( inject ) ,
735822 };
736823
737824 addr_location__init (& al );
@@ -743,13 +830,8 @@ int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *e
743830 }
744831
745832 if (thread__find_map (thread , sample -> cpumode , sample -> ip , & al )) {
746- struct dso * dso = map__dso (al .map );
747-
748- if (!dso__hit (dso )) {
749- dso__set_hit (dso );
750- dso__inject_build_id (dso , tool , machine ,
751- sample -> cpumode , map__flags (al .map ));
752- }
833+ mark_dso_hit (tool , sample , machine , args .mmap_evsel , al .map ,
834+ /*sample_in_dso=*/ true);
753835 }
754836
755837 sample__for_each_callchain_node (thread , evsel , sample , PERF_MAX_STACK_DEPTH ,
@@ -1159,17 +1241,27 @@ static int process_build_id(const struct perf_tool *tool,
11591241static int synthesize_build_id (struct perf_inject * inject , struct dso * dso , pid_t machine_pid )
11601242{
11611243 struct machine * machine = perf_session__findnew_machine (inject -> session , machine_pid );
1162- u8 cpumode = dso__is_in_kernel_space (dso ) ?
1163- PERF_RECORD_MISC_GUEST_KERNEL :
1164- PERF_RECORD_MISC_GUEST_USER ;
1244+ struct perf_sample synth_sample = {
1245+ .pid = -1 ,
1246+ .tid = -1 ,
1247+ .time = -1 ,
1248+ .stream_id = -1 ,
1249+ .cpu = -1 ,
1250+ .period = 1 ,
1251+ .cpumode = dso__is_in_kernel_space (dso )
1252+ ? PERF_RECORD_MISC_GUEST_KERNEL
1253+ : PERF_RECORD_MISC_GUEST_USER ,
1254+ };
11651255
11661256 if (!machine )
11671257 return - ENOMEM ;
11681258
11691259 dso__set_hit (dso );
11701260
1171- return perf_event__synthesize_build_id (& inject -> tool , dso , cpumode ,
1172- process_build_id , machine );
1261+ return perf_event__synthesize_build_id (& inject -> tool , & synth_sample , machine ,
1262+ process_build_id , inject__mmap_evsel (inject ),
1263+ /*misc=*/ synth_sample .cpumode ,
1264+ dso__bid (dso ), dso__long_name (dso ));
11731265}
11741266
11751267static int guest_session__add_build_ids_cb (struct dso * dso , void * data )
0 commit comments