Add support for CPU cycles measurement
diff --git a/common.h b/common.h
index 3e02e19..f2d601a 100644
--- a/common.h
+++ b/common.h
@@ -52,7 +52,8 @@
_HF_DYNFILE_NONE = 0x0,
_HF_DYNFILE_INSTR_COUNT = 0x1,
_HF_DYNFILE_BRANCH_COUNT = 0x2,
- _HF_DYNFILE_UNIQUE_PC_COUNT = 0x4,
+ _HF_DYNFILE_CYCLE_COUNT = 0x4,
+ _HF_DYNFILE_UNIQUE_PC_COUNT = 0x8,
} dynFileMethod_t;
typedef struct {
@@ -82,7 +83,7 @@
uint8_t *dynamicFileBest;
size_t dynamicFileBestSz;
dynFileMethod_t dynFileMethod;
- int64_t branchBestCnt[3];
+ int64_t branchBestCnt[4];
int dynamicRegressionCnt;
uint64_t dynamicCutOffAddr;
pthread_mutex_t dynamicFile_mutex;
@@ -101,7 +102,7 @@
/* For linux/ code */
uint8_t *dynamicFile;
- int64_t branchCnt[3];
+ int64_t branchCnt[4];
size_t dynamicFileSz;
} fuzzer_t;
diff --git a/fuzz.c b/fuzz.c
index bda93ff..abbf0f0 100644
--- a/fuzz.c
+++ b/fuzz.c
@@ -69,7 +69,7 @@
while (pthread_mutex_lock(&hfuzz->dynamicFile_mutex)) ;
if (hfuzz->inputFile && hfuzz->branchBestCnt[0] == 0 && hfuzz->branchBestCnt[1] == 0
- && hfuzz->branchBestCnt[2] == 0) {
+ && hfuzz->branchBestCnt[2] == 0 && hfuzz->branchBestCnt[3] == 0) {
size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], hfuzz->dynamicFileBest,
hfuzz->maxFileSz);
if (fileSz == 0) {
@@ -91,7 +91,8 @@
while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ;
/* The first pass should be on an empty/initial file */
- if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0) {
+ if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0
+ || hfuzz->branchBestCnt[3] > 0) {
mangle_Resize(hfuzz, &fuzzer->dynamicFileSz);
mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz);
}
@@ -213,9 +214,7 @@
.exception = 0,
.dynamicFileSz = 0,
.dynamicFile = malloc(hfuzz->maxFileSz),
- .branchCnt[0] = 0,
- .branchCnt[1] = 0,
- .branchCnt[2] = 0,
+ .branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0,},
.report = {'\0'}
};
if (fuzzer.dynamicFile == NULL) {
@@ -275,16 +274,18 @@
int64_t diff0 = hfuzz->branchBestCnt[0] - fuzzer.branchCnt[0];
int64_t diff1 = hfuzz->branchBestCnt[1] - fuzzer.branchCnt[1];
int64_t diff2 = hfuzz->branchBestCnt[2] - fuzzer.branchCnt[2];
+ int64_t diff3 = hfuzz->branchBestCnt[3] - fuzzer.branchCnt[3];
if (diff0 <= hfuzz->dynamicRegressionCnt && diff1 <= hfuzz->dynamicRegressionCnt
- && diff2 <= hfuzz->dynamicRegressionCnt) {
+ && diff2 <= hfuzz->dynamicRegressionCnt && diff3 <= hfuzz->dynamicRegressionCnt) {
LOGMSG(l_INFO,
"New BEST feedback: File Size (New/Old): %zu/%zu', Perf feedback (Curr, High): %"
- PRId64 "/%" PRId64 "/%" PRId64 ", %" PRId64 "/%" PRId64 "/%" PRId64,
- fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz, fuzzer.branchCnt[0],
- fuzzer.branchCnt[1], fuzzer.branchCnt[2], hfuzz->branchBestCnt[0],
- hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2]);
+ PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 ", %" PRId64 "/%" PRId64 "/%" PRId64
+ "/%" PRId64, fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz, fuzzer.branchCnt[0],
+ fuzzer.branchCnt[1], fuzzer.branchCnt[2], fuzzer.branchCnt[3],
+ hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2],
+ hfuzz->branchBestCnt[3]);
memcpy(hfuzz->dynamicFileBest, fuzzer.dynamicFile, fuzzer.dynamicFileSz);
@@ -298,6 +299,9 @@
hfuzz->branchBestCnt[2] =
fuzzer.branchCnt[2] >
hfuzz->branchBestCnt[2] ? fuzzer.branchCnt[2] : hfuzz->branchBestCnt[2];
+ hfuzz->branchBestCnt[3] =
+ fuzzer.branchCnt[3] >
+ hfuzz->branchBestCnt[3] ? fuzzer.branchCnt[3] : hfuzz->branchBestCnt[3];
#define _HF_CURRENT_BEST "CURRENT_BEST"
#define _HF_CURRENT_BEST_TMP ".tmp.CURRENT_BEST"
@@ -336,9 +340,7 @@
.exception = 0,
.dynamicFileSz = 0,
.dynamicFile = malloc(hfuzz->maxFileSz),
- .branchCnt[0] = 0,
- .branchCnt[1] = 0,
- .branchCnt[2] = 0,
+ .branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0,},
.report = {'\0'}
};
if (fuzzer.dynamicFile == NULL) {
diff --git a/honggfuzz.c b/honggfuzz.c
index 0c6f085..9040b03 100644
--- a/honggfuzz.c
+++ b/honggfuzz.c
@@ -90,6 +90,7 @@
" (default: " AB "none" AC ")\n"
" Available counters: \n"
" " AB "'i' " AC "- PERF_COUNT_HW_INSTRUCTIONS (total IPs)\n"
+ " " AB "'c' " AC "- PERF_COUNT_HW_REF_CPU_CYCLES (total CPU cycles)\n"
" " AB "'b' " AC "- PERF_COUNT_HW_BRANCH_INSTRUCTIONS (total jumps/calls)\n"
" " AB "'p' " AC "- PERF_SAMPLE_IP/PERF_SAMPLE_ADDR (unique branches)\n"
" (newer Intel CPUs only)\n"
@@ -145,9 +146,7 @@
.dynFileMethod = _HF_DYNFILE_NONE,
.dynamicFileBest = NULL,
.dynamicFileBestSz = 1,
- .branchBestCnt[0] = 0,
- .branchBestCnt[1] = 0,
- .branchBestCnt[2] = 0,
+ .branchBestCnt = {[0 ... (ARRAYSIZE(hfuzz.branchBestCnt) - 1)] = 0,},
.dynamicRegressionCnt = 0,
.dynamicCutOffAddr = ~(0ULL),
.dynamicFile_mutex = PTHREAD_MUTEX_INITIALIZER,
@@ -202,6 +201,9 @@
case 'b':
hfuzz.dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
break;
+ case 'c':
+ hfuzz.dynFileMethod |= _HF_DYNFILE_CYCLE_COUNT;
+ break;
case 'p':
hfuzz.dynFileMethod |= _HF_DYNFILE_UNIQUE_PC_COUNT;
break;
diff --git a/linux/perf.c b/linux/perf.c
index 7ad32a9..2bbc34c 100644
--- a/linux/perf.c
+++ b/linux/perf.c
@@ -220,6 +220,11 @@
pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
pe.inherit = 1;
break;
+ case _HF_DYNFILE_CYCLE_COUNT:
+ LOGMSG(l_DEBUG, "Using: PERF_COUNT_HW_REF_CPU_CYCLES for PID: %d", pid);
+ pe.config = PERF_COUNT_HW_REF_CPU_CYCLES;
+ pe.inherit = 1;
+ break;
case _HF_DYNFILE_UNIQUE_PC_COUNT:
bzero(perfBloom, sizeof(perfBloom));
LOGMSG(l_DEBUG,
@@ -306,6 +311,7 @@
perfFd[0] = -1;
perfFd[1] = -1;
perfFd[2] = -1;
+ perfFd[3] = -1;
if (hfuzz->dynFileMethod & _HF_DYNFILE_INSTR_COUNT) {
if (arch_perfOpen(pid, _HF_DYNFILE_INSTR_COUNT, &perfFd[0]) == false) {
@@ -313,6 +319,7 @@
close(perfFd[0]);
close(perfFd[1]);
close(perfFd[2]);
+ close(perfFd[3]);
return false;
}
}
@@ -322,6 +329,17 @@
close(perfFd[0]);
close(perfFd[1]);
close(perfFd[2]);
+ close(perfFd[3]);
+ return false;
+ }
+ }
+ if (hfuzz->dynFileMethod & _HF_DYNFILE_CYCLE_COUNT) {
+ if (arch_perfOpen(pid, _HF_DYNFILE_CYCLE_COUNT, &perfFd[2]) == false) {
+ LOGMSG(l_ERROR, "Cannot set up perf for PID=%d (_HF_DYNFILE_CYCLE_COUNT)", pid);
+ close(perfFd[0]);
+ close(perfFd[1]);
+ close(perfFd[2]);
+ close(perfFd[3]);
return false;
}
}
@@ -362,6 +380,15 @@
close(perfFd[1]);
}
+ uint64_t cycleCount = 0;
+ if (hfuzz->dynFileMethod & _HF_DYNFILE_CYCLE_COUNT) {
+ ioctl(perfFd[2], PERF_EVENT_IOC_DISABLE, 0);
+ if (read(perfFd[2], &cycleCount, sizeof(cycleCount)) != sizeof(cycleCount)) {
+ LOGMSG_P(l_ERROR, "read(perfFd='%d') failed", perfFd);
+ }
+ close(perfFd[2]);
+ }
+
uint64_t edgeCount = 0;
if (hfuzz->dynFileMethod & _HF_DYNFILE_UNIQUE_PC_COUNT) {
arch_perfMmapParse();
@@ -381,13 +408,14 @@
fuzzer->branchCnt[0] = instrCount;
fuzzer->branchCnt[1] = branchCount;
- fuzzer->branchCnt[2] = edgeCount;
+ fuzzer->branchCnt[2] = cycleCount;
+ fuzzer->branchCnt[3] = edgeCount;
LOGMSG(l_INFO,
"File size (New/Best): %zu/%zu, Perf feedback: Best: [%" PRIu64 ",%" PRIu64 ",%" PRIu64
- "] / New: [%" PRIu64 ",%" PRIu64 ",%" PRIu64 "]", fuzzer->dynamicFileSz,
- hfuzz->dynamicFileBestSz, hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1],
- hfuzz->branchBestCnt[2], fuzzer->branchCnt[0], fuzzer->branchCnt[1],
- fuzzer->branchCnt[2]);
+ ",%" PRIu64 "] / New: [%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "]",
+ fuzzer->dynamicFileSz, hfuzz->dynamicFileBestSz, hfuzz->branchBestCnt[0],
+ hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2], hfuzz->branchBestCnt[3],
+ fuzzer->branchCnt[0], fuzzer->branchCnt[1], fuzzer->branchCnt[2], fuzzer->branchCnt[3]);
return;
}