@@ -130,6 +130,7 @@ struct perf_inject {
130
130
struct perf_file_section secs [HEADER_FEAT_BITS ];
131
131
struct guest_session guest_session ;
132
132
struct strlist * known_build_ids ;
133
+ const struct evsel * mmap_evsel ;
133
134
};
134
135
135
136
struct event_entry {
@@ -138,8 +139,13 @@ struct event_entry {
138
139
union perf_event event [];
139
140
};
140
141
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 );
143
149
144
150
static int output_bytes (struct perf_inject * inject , void * buf , size_t sz )
145
151
{
@@ -422,6 +428,28 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename,
422
428
return dso ;
423
429
}
424
430
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
+
425
453
static int perf_event__repipe_common_mmap (const struct perf_tool * tool ,
426
454
union perf_event * event ,
427
455
struct perf_sample * sample ,
@@ -469,12 +497,28 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
469
497
}
470
498
471
499
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
+ }
474
508
}
475
509
} 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
+
476
520
/* 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 );
478
522
479
523
if (err ) {
480
524
dso__put (dso );
@@ -667,58 +711,95 @@ static bool perf_inject__lookup_known_build_id(struct perf_inject *inject,
667
711
return false;
668
712
}
669
713
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 )
672
721
{
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 );
675
723
int err ;
676
724
677
- if (is_anon_memory (dso__long_name ( dso ) ) || flags & MAP_HUGETLB )
725
+ if (is_anon_memory (filename ) || flags & MAP_HUGETLB )
678
726
return 0 ;
679
- if (is_no_dso_memory (dso__long_name ( dso ) ))
727
+ if (is_no_dso_memory (filename ))
680
728
return 0 ;
681
729
682
730
if (inject -> known_build_ids != NULL &&
683
731
perf_inject__lookup_known_build_id (inject , dso ))
684
732
return 1 ;
685
733
686
734
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 );
688
736
return -1 ;
689
737
}
690
738
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 );
693
743
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 );
695
745
return -1 ;
696
746
}
697
747
698
748
return 0 ;
699
749
}
700
750
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
+
701
789
struct mark_dso_hit_args {
702
790
const struct perf_tool * tool ;
791
+ struct perf_sample * sample ;
703
792
struct machine * machine ;
704
- u8 cpumode ;
793
+ const struct evsel * mmap_evsel ;
705
794
};
706
795
707
796
static int mark_dso_hit_callback (struct callchain_cursor_node * node , void * data )
708
797
{
709
798
struct mark_dso_hit_args * args = data ;
710
799
struct map * map = node -> ms .map ;
711
800
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);
722
803
}
723
804
724
805
int 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
728
809
{
729
810
struct addr_location al ;
730
811
struct thread * thread ;
812
+ struct perf_inject * inject = container_of (tool , struct perf_inject , tool );
731
813
struct mark_dso_hit_args args = {
732
814
.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 ,
733
820
.machine = machine ,
734
- .cpumode = sample -> cpumode ,
821
+ .mmap_evsel = inject__mmap_evsel ( inject ) ,
735
822
};
736
823
737
824
addr_location__init (& al );
@@ -743,13 +830,8 @@ int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *e
743
830
}
744
831
745
832
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);
753
835
}
754
836
755
837
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,
1159
1241
static int synthesize_build_id (struct perf_inject * inject , struct dso * dso , pid_t machine_pid )
1160
1242
{
1161
1243
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
+ };
1165
1255
1166
1256
if (!machine )
1167
1257
return - ENOMEM ;
1168
1258
1169
1259
dso__set_hit (dso );
1170
1260
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 ));
1173
1265
}
1174
1266
1175
1267
static int guest_session__add_build_ids_cb (struct dso * dso , void * data )
0 commit comments