@@ -268,19 +268,20 @@ struct perf_event_sample {
268
268
uint64_t period;
269
269
};
270
270
271
- struct perf_event_mmap {
271
+ struct perf_event_mmap_common {
272
272
struct perf_event_header header;
273
273
274
274
uint32_t pid, tid;
275
275
uint64_t start, extent, pgoff;
276
+ };
277
+
278
+ struct perf_event_mmap {
279
+ struct perf_event_mmap_common mmap_common;
276
280
char filename[1 ];
277
281
};
278
282
279
283
struct perf_event_mmap2 {
280
- struct perf_event_header header;
281
-
282
- uint32_t pid, tid;
283
- uint64_t start, extent, pgoff;
284
+ struct perf_event_mmap_common mmap_common;
284
285
uint32_t maj, min;
285
286
uint64_t ino, ino_generation;
286
287
uint32_t prot, flags;
@@ -292,12 +293,6 @@ struct perf_trace_event_type {
292
293
char str[64 ];
293
294
};
294
295
295
- struct perf_sample_id {
296
- uint32_t pid, tid;
297
- uint64_t time;
298
- uint64_t id;
299
- };
300
-
301
296
enum perf_type_id {
302
297
PERF_TYPE_HARDWARE = 0 ,
303
298
PERF_TYPE_SOFTWARE = 1 ,
@@ -598,6 +593,7 @@ class PerfReader {
598
593
void readAttrs ();
599
594
void readEventDesc ();
600
595
void readDataStream ();
596
+ void registerNewMapping (unsigned char *Buf, const char *FileName);
601
597
unsigned char *readEvent (unsigned char *);
602
598
perf_event_sample parseEvent (unsigned char *Buf, uint64_t Layout);
603
599
void emitLine (uint64_t PC, std::map<const char *, uint64_t > *Counters,
@@ -719,7 +715,7 @@ void PerfReader::readAttrs() {
719
715
720
716
// Weirdness of perf: if there is only one event descriptor, that
721
717
// event descriptor can be referred to by ANY id!
722
- if (NumEvents == 1 && NumIDs == 0 ) {
718
+ if (NumEvents == 1 ) {
723
719
EventIDs[0 ] = Str;
724
720
EventLayouts[0 ] = attr->sample_type ;
725
721
}
@@ -758,7 +754,7 @@ void PerfReader::readEventDesc() {
758
754
759
755
// Weirdness of perf: if there is only one event descriptor, that
760
756
// event descriptor can be referred to by ANY id!
761
- if (NumEvents == 1 && NumIDs == 0 ) {
757
+ if (NumEvents == 1 ) {
762
758
EventIDs[0 ] = Str;
763
759
EventLayouts[0 ] = Layout;
764
760
}
@@ -771,45 +767,57 @@ void PerfReader::readEventDesc() {
771
767
}
772
768
}
773
769
770
+ static uint64_t getTimeFromSampleId (unsigned char *EndOfStruct,
771
+ uint64_t Layout) {
772
+ uint64_t *Ptr = (uint64_t *)EndOfStruct;
773
+ // Each of the PERF_SAMPLE_* bits tested below adds an 8-byte field.
774
+ if (Layout & PERF_SAMPLE_IDENTIFIER)
775
+ --Ptr;
776
+ if (Layout & PERF_SAMPLE_CPU)
777
+ --Ptr;
778
+ if (Layout & PERF_SAMPLE_STREAM_ID)
779
+ --Ptr;
780
+ if (Layout & PERF_SAMPLE_ID)
781
+ --Ptr;
782
+ assert (Layout & PERF_SAMPLE_TIME);
783
+ --Ptr;
784
+ return *Ptr;
785
+ }
786
+
787
+ void PerfReader::registerNewMapping (unsigned char *Buf, const char *Filename) {
788
+ perf_event_mmap_common *E = (perf_event_mmap_common *)Buf;
789
+ auto MapID = Maps.size ();
790
+ // EXEC ELF objects aren't relocated. DYN ones are,
791
+ // so if it's a DYN object adjust by subtracting the
792
+ // map base.
793
+ bool IsSO = IsSharedObject (BinaryCacheRoot + std::string (Filename));
794
+ uint64_t End = E->start + E->extent ;
795
+ uint64_t Adjust = IsSO ? E->start - E->pgoff : 0 ;
796
+ Maps.push_back ({E->start , End, Adjust, Filename});
797
+
798
+ unsigned char *EndOfEvent = Buf + E->header .size ;
799
+ // FIXME: The first EventID is used for every event.
800
+ // FIXME: The code assumes perf_event_attr.sample_id_all is set.
801
+ uint64_t Time = getTimeFromSampleId (EndOfEvent, EventLayouts.begin ()->second );
802
+ auto &CurrentMap = CurrentMaps[Time];
803
+ CurrentMap.insert ({E->start , MapID});
804
+ }
805
+
774
806
unsigned char *PerfReader::readEvent (unsigned char *Buf) {
775
807
perf_event_header *E = (perf_event_header *)Buf;
776
808
switch (E->type ) {
777
809
case PERF_RECORD_MMAP:
778
810
{
779
811
perf_event_mmap *E = (perf_event_mmap *)Buf;
780
- auto MapID = Maps.size ();
781
- // EXEC ELF objects aren't relocated. DYN ones are,
782
- // so if it's a DYN object adjust by subtracting the
783
- // map base.
784
- bool IsSO = IsSharedObject (BinaryCacheRoot + std::string (E->filename ));
785
- Maps.push_back ({E->start , E->start + E->extent ,
786
- IsSO ? E->start - E->pgoff : 0 , E->filename });
787
-
788
- // FIXME: use EventLayouts.begin()->second!
789
- perf_sample_id *ID =
790
- (perf_sample_id *)(Buf + E->header .size - sizeof (perf_sample_id));
791
- auto &CurrentMap = CurrentMaps[ID->time ];
792
- CurrentMap.insert ({E->start , MapID});
812
+ registerNewMapping (Buf, E->filename );
793
813
}
794
814
break ;
795
815
case PERF_RECORD_MMAP2:
796
816
{
797
817
perf_event_mmap2 *E = (perf_event_mmap2 *)Buf;
798
818
if (!(E->prot & PROT_EXEC))
799
819
break ;
800
- auto MapID = Maps.size ();
801
- // EXEC ELF objects aren't relocated. DYN ones are,
802
- // so if it's a DYN object adjust by subtracting the
803
- // map base.
804
- bool IsSO = IsSharedObject (BinaryCacheRoot + std::string (E->filename ));
805
- Maps.push_back ({E->start , E->start + E->extent ,
806
- IsSO ? E->start - E->pgoff : 0 , E->filename });
807
-
808
- // FIXME: use EventLayouts.begin()->second!
809
- perf_sample_id *ID =
810
- (perf_sample_id *)(Buf + E->header .size - sizeof (perf_sample_id));
811
- auto &CurrentMap = CurrentMaps[ID->time ];
812
- CurrentMap.insert ({E->start , MapID});
820
+ registerNewMapping (Buf, E->filename );
813
821
}
814
822
break ;
815
823
case PERF_RECORD_SAMPLE:
0 commit comments