diff --git a/include/pcerrc.h b/include/pcerrc.h index 13c04e9b7f221c30ffd1226e899ba587ec89bd93..7a1393147e4b654700d1f5e2ee528e38f597ff50 100644 --- a/include/pcerrc.h +++ b/include/pcerrc.h @@ -79,6 +79,7 @@ extern "C" { #define LIBPERF_ERR_COUNT_OVERFLOW 1035 #define LIBPERF_ERR_INVALID_GROUP_SPE 1036 #define LIBPERF_ERR_INVALID_GROUP_ALL_UNCORE 1037 +#define LIBPERF_ERR_BUFFER_CORRUPTED 1038 #define UNKNOWN_ERROR 9999 diff --git a/pmu/sample_process.cpp b/pmu/sample_process.cpp index fcd1bfaf482cee26d80bd78258a97bbfef0610d6..85d7d7b91b2bad087cf73a296e89535f77e480d0 100644 --- a/pmu/sample_process.cpp +++ b/pmu/sample_process.cpp @@ -16,12 +16,14 @@ #include #include #include "pcerrc.h" +#include "pcerr.h" #include "evt.h" #include "sample_process.h" #define PAGE_SIZE (sysconf(_SC_PAGESIZE)) #define MB() asm volatile("dmb ish" ::: "memory") static constexpr int MAX_DATA_SIZE = 8192; +using namespace pcerr; #define PerfRingbufferSmpStoreRelease(p, v) \ ({ \ union { \ @@ -102,6 +104,10 @@ static inline union KUNPENG_PMU::PerfEvent *PerfMmapRead(KUNPENG_PMU::PerfMmap & event = (union KUNPENG_PMU::PerfEvent *)&data[*startPointer & map.mask]; size = event->header.size; + if (__glibc_unlikely(size == 0)) { + New(LIBPERF_ERR_BUFFER_CORRUPTED); + return nullptr; + } if (__glibc_unlikely(size < sizeof(event->header) || diff < size)) { return nullptr; diff --git a/pmu/sampler.cpp b/pmu/sampler.cpp index b71825d136dba2fa5027495d6a7257388e2df299..45bb0cacf8b3c6038ce48d9c9f8135cfcddce81d 100644 --- a/pmu/sampler.cpp +++ b/pmu/sampler.cpp @@ -253,6 +253,9 @@ int KUNPENG_PMU::PerfSampler::Read(vector &data, std::vectorReadRingBuffer(data, sampleIps); + if (__glibc_unlikely(Perrorno() == LIBPERF_ERR_BUFFER_CORRUPTED)) { + return Perrorno(); + } if (this->pid == -1) { FillComm(cnt, data.size(), data); } diff --git a/pmu/spe.cpp b/pmu/spe.cpp index 99b7a893afb9df0d85c7abcdfe0b2758ec1bba25..158e7c16597afa0890579e1642ba0aaae5714872 100644 --- a/pmu/spe.cpp +++ b/pmu/spe.cpp @@ -344,7 +344,7 @@ static void ParseContextSwitch(PerfEventSampleContextSwitch *contextSample, Cont } } -void Spe::CoreDummyData(struct SpeCoreContext *context, struct ContextSwitchData *data, int size, int pageSize) +int Spe::CoreDummyData(struct SpeCoreContext *context, struct ContextSwitchData *data, int size, int pageSize) { uint64_t maxNum = size / sizeof(struct ContextSwitchData); uint64_t num = 1; @@ -358,6 +358,9 @@ void Spe::CoreDummyData(struct SpeCoreContext *context, struct ContextSwitchData while ((dataTail < dataHead) && (num < maxNum)) { uint64_t off = dataTail % mpage->data_size; struct perf_event_header *header = (struct perf_event_header *)(ringBuf + off); + if (__glibc_unlikely(header->size == 0)) { + return LIBPERF_ERR_BUFFER_CORRUPTED; + } if (header->type == PERF_RECORD_MMAP && symbolMode != NO_SYMBOL_RESOLVE) { struct PerfRecordMmap *sample = (struct PerfRecordMmap *)header; @@ -528,7 +531,11 @@ int Spe::SpeReadData(struct SpeContext *context, struct SpeRecord *buf, int size { int remainSize = size; int dummySize = context->dummyMmapSize; - CoreDummyData(context->coreCtxes, dummyData, dummySize, context->pageSize); + int err = CoreDummyData(context->coreCtxes, dummyData, dummySize, context->pageSize); + if (err != SUCCESS) { + New(err); + return -1; + } buf = CoreSpeData(context->coreCtxes, dummyData, buf, &remainSize, context->pageSize, cpu); return size - remainSize; } @@ -627,7 +634,7 @@ int Spe::Read() pidRecords[rec->tid].push_back(rec); } status |= READ; - if (Perrorno() == LIBPERF_ERR_KERNEL_NOT_SUPPORT) { + if (Perrorno() == LIBPERF_ERR_KERNEL_NOT_SUPPORT || Perrorno() == LIBPERF_ERR_BUFFER_CORRUPTED) { return Perrorno(); } return SUCCESS; diff --git a/pmu/spe.h b/pmu/spe.h index fc937d1ea8b633c19faa64c9cb4663a2dfc428d9..09e50ded50cd6749c5f598e2508e95dda6426c1b 100644 --- a/pmu/spe.h +++ b/pmu/spe.h @@ -199,7 +199,7 @@ public: private: int SpeReadData(struct SpeContext *context, struct SpeRecord *buf, int size); - void CoreDummyData(struct SpeCoreContext *context, struct ContextSwitchData *data, int size, int pageSize); + int CoreDummyData(struct SpeCoreContext *context, struct ContextSwitchData *data, int size, int pageSize); void UpdateProcMap(__u32 ppid, __u32 pid); const unsigned short NONE = 0; diff --git a/python/modules/kperf/perror.py b/python/modules/kperf/perror.py index 6f5cfb3f56cf990373ea8fb48c1ee9cfbc2e5de0..a5c6fe3d9e3003169882c23c9d53d6fcce4ba528 100644 --- a/python/modules/kperf/perror.py +++ b/python/modules/kperf/perror.py @@ -78,6 +78,7 @@ class Error: LIBPERF_ERR_COUNT_OVERFLOW = 1035 LIBPERF_ERR_INVALID_GROUP_SPE = 1036 LIBPERF_ERR_INVALID_GROUP_ALL_UNCORE = 1037 + LIBPERF_ERR_BUFFER_CORRUPTED = 1038 UNKNOWN_ERROR = 9999