display.c revision 91c687c62700001b68d24b8ce4a27ce3eba650d0
1/*
2 *
3 * honggfuzz - display statistics
4 * -----------------------------------------
5 *
6 * Author: Robert Swiecki <swiecki@google.com>
7 *
8 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
12 * a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19 * implied. See the License for the specific language governing
20 * permissions and limitations under the License.
21 *
22 */
23
24#define _WITH_DPRINTF
25
26#include "common.h"
27#include "display.h"
28
29#include <inttypes.h>
30#include <math.h>
31#include <string.h>
32#include <stdarg.h>
33#include <stdio.h>
34#include <unistd.h>
35
36#include "log.h"
37#include "util.h"
38
39#define ESC_CLEAR "\033[H\033[2J"
40#define ESC_NAV(x,y) "\033["#x";"#y"H"
41#define ESC_BOLD "\033[1m"
42#define ESC_RED "\033[31m"
43#define ESC_RESET "\033[0m"
44
45#if defined(_HF_ARCH_LINUX)
46#define _HF_MONETARY_MOD "'"
47#else
48#define _HF_MONETARY_MOD ""
49#endif
50
51static void display_put(const char *fmt, ...)
52{
53    va_list args;
54    va_start(args, fmt);
55    vdprintf(STDOUT_FILENO, fmt, args);
56    va_end(args);
57}
58
59static void display_printKMG(uint64_t val)
60{
61    if (val >= 1000000000UL) {
62        display_put(" [%.2lfG]", (double)val / 1000000.0);
63    } else if (val >= 1000000UL) {
64        display_put(" [%.2lfM]", (double)val / 1000000.0);
65    } else if (val >= 1000UL) {
66        display_put(" [%.2lfk]", (double)val / 1000.0);
67    }
68}
69
70static double getCpuUse()
71{
72    static uint64_t prevUserT = 0UL;
73    static uint64_t prevSystemT = 0UL;
74
75    FILE *f = fopen("/proc/stat", "r");
76    if (f == NULL) {
77        return NAN;
78    }
79    defer {
80        fclose(f);
81    };
82    uint64_t userT, niceT, systemT, idleT;
83    if (fscanf
84        (f, "cpu  %" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &userT, &niceT, &systemT,
85         &idleT) != 4) {
86        LOG_W("fscanf('/proc/stat') != 4");
87        return NAN;
88    }
89
90    if (prevUserT == 0UL || prevSystemT == 0UL) {
91        prevUserT = userT;
92        prevSystemT = systemT;
93        return NAN;
94    }
95
96    double cpuUse =
97        (double)(((systemT - prevSystemT) + (userT - prevUserT))) / sysconf(_SC_CLK_TCK);
98    prevUserT = userT;
99    prevSystemT = systemT;
100    return cpuUse * 100;
101}
102
103static void display_displayLocked(honggfuzz_t * hfuzz)
104{
105    unsigned long elapsed_second = (unsigned long)(time(NULL) - hfuzz->timeStart);
106    unsigned int day, hour, min, second;
107    char time_elapsed_str[64];
108    if (elapsed_second < 24 * 3600) {
109        hour = elapsed_second / 3600;
110        min = (elapsed_second - 3600 * hour) / 60;
111        second = elapsed_second - hour * 3600 - min * 60;
112        snprintf(time_elapsed_str, sizeof(time_elapsed_str), "%u hrs %u min %u sec", hour,
113                 min, second);
114    } else {
115        day = elapsed_second / 24 / 3600;
116        elapsed_second = elapsed_second - day * 24 * 3600;
117        hour = elapsed_second / 3600;
118        min = (elapsed_second - 3600 * hour) / 60;
119        second = elapsed_second - hour * 3600 - min * 60;
120        snprintf(time_elapsed_str, sizeof(time_elapsed_str),
121                 "%u days %u hrs %u min %u sec", day, hour, min, second);
122    }
123
124    size_t curr_exec_cnt = ATOMIC_GET(hfuzz->mutationsCnt);
125    /*
126     * We increase the mutation counter unconditionally in threads, but if it's
127     * above hfuzz->mutationsMax we don't really execute the fuzzing loop.
128     * Therefore at the end of fuzzing, the mutation counter might be higher
129     * than hfuzz->mutationsMax
130     */
131    if (hfuzz->mutationsMax > 0 && curr_exec_cnt > hfuzz->mutationsMax) {
132        curr_exec_cnt = hfuzz->mutationsMax;
133    }
134    float exeProgress = 0.0f;
135    if (hfuzz->mutationsMax > 0) {
136        exeProgress = ((float)curr_exec_cnt * 100 / hfuzz->mutationsMax);
137    }
138
139    static size_t prev_exec_cnt = 0UL;
140    uintptr_t exec_per_sec = curr_exec_cnt - prev_exec_cnt;
141    prev_exec_cnt = curr_exec_cnt;
142    MX_SCOPED_LOCK(logMutexGet());
143    display_put("%s", ESC_CLEAR);
144    display_put("=============================| %s v.%s |============================\n", PROG_NAME,
145                PROG_VERSION);
146    display_put("Iterations: " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET, curr_exec_cnt);
147    display_printKMG(curr_exec_cnt);
148    if (hfuzz->mutationsMax) {
149        display_put(" (out of: " ESC_BOLD "%zu" ESC_RESET " [" ESC_BOLD "%.2f%%" ESC_RESET
150                    "])", hfuzz->mutationsMax, exeProgress);
151    }
152    display_put("\n");
153    char start_time_str[128];
154    util_getLocalTime("%F %T", start_time_str, sizeof(start_time_str), hfuzz->timeStart);
155    display_put("Run time: " ESC_BOLD "%s" ESC_RESET " (since: " ESC_BOLD "%s" ESC_RESET
156                ")\n", time_elapsed_str, start_time_str);
157    display_put("Input file/dir: '" ESC_BOLD "%s" ESC_RESET "'\n", hfuzz->inputFile);
158    display_put("Fuzzed cmd: '" ESC_BOLD "%s" ESC_RESET "'\n", hfuzz->cmdline_txt);
159    if (hfuzz->linux.pid > 0) {
160        display_put("Remote cmd [" ESC_BOLD "%d" ESC_RESET "]: '" ESC_BOLD "%s" ESC_RESET
161                    "'\n", hfuzz->linux.pid, hfuzz->linux.pidCmd);
162    }
163
164    display_put("Fuzzing threads: " ESC_BOLD "%zu" ESC_RESET ", CPUs: " ESC_BOLD "%ld" ESC_RESET
165                ", OS load: " ESC_BOLD "%.1lf%%" ESC_RESET, hfuzz->threadsMax,
166                sysconf(_SC_NPROCESSORS_ONLN), getCpuUse());
167
168    display_put("\n%s per second: " ESC_BOLD "% " _HF_MONETARY_MOD "zu" ESC_RESET
169                " (avg: " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET ")\n",
170                hfuzz->persistent ? "Rounds" : "Execs", exec_per_sec,
171                elapsed_second ? (curr_exec_cnt / elapsed_second) : 0);
172    /* If dry run, print also the input file count */
173    if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
174        display_put("Input Files: '" ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET "'\n",
175                    hfuzz->fileCnt);
176    }
177
178    uint64_t crashesCnt = ATOMIC_GET(hfuzz->crashesCnt);
179    /* colored the crash count as red when exist crash */
180    display_put("Crashes: " ESC_BOLD "%s" "%zu" ESC_RESET " (unique: %s" ESC_BOLD "%zu"
181                ESC_RESET ", blacklist: " ESC_BOLD "%zu" ESC_RESET ", verified: "
182                ESC_BOLD "%zu" ESC_RESET ")\n", crashesCnt > 0 ? ESC_RED : "",
183                hfuzz->crashesCnt, crashesCnt > 0 ? ESC_RED : "",
184                ATOMIC_GET(hfuzz->uniqueCrashesCnt), ATOMIC_GET(hfuzz->blCrashesCnt),
185                ATOMIC_GET(hfuzz->verifiedCrashesCnt));
186    display_put("Timeouts (%" _HF_MONETARY_MOD "zu sec): " ESC_BOLD "%"
187                _HF_MONETARY_MOD "zu" ESC_RESET "\n", hfuzz->tmOut,
188                ATOMIC_GET(hfuzz->timeoutedCnt));
189    /* Feedback data sources are enabled. Start with common headers. */
190    if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE || hfuzz->useSanCov) {
191        display_put("File corpus size: " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET "\n",
192                    hfuzz->dynfileqCnt);
193        display_put("Coverage (max):\n");
194    }
195
196    /* HW perf specific counters */
197    if (hfuzz->dynFileMethod & _HF_DYNFILE_INSTR_COUNT) {
198        display_put("  - instructions:    " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
199                    "\n", ATOMIC_GET(hfuzz->linux.hwCnts.cpuInstrCnt));
200    }
201    if (hfuzz->dynFileMethod & _HF_DYNFILE_BRANCH_COUNT) {
202        display_put("  - branches:        " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
203                    "\n", ATOMIC_GET(hfuzz->linux.hwCnts.cpuBranchCnt));
204    }
205    if (hfuzz->dynFileMethod & _HF_DYNFILE_BTS_BLOCK) {
206        display_put("  - BTS blocks:      " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
207                    "\n", ATOMIC_GET(hfuzz->linux.hwCnts.bbCnt));
208    }
209    if (hfuzz->dynFileMethod & _HF_DYNFILE_BTS_EDGE) {
210        display_put("  - BTS edges:       " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
211                    "\n", ATOMIC_GET(hfuzz->linux.hwCnts.bbCnt));
212    }
213    if (hfuzz->dynFileMethod & _HF_DYNFILE_IPT_BLOCK) {
214        display_put("  - PT blocks:       " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
215                    "\n", ATOMIC_GET(hfuzz->linux.hwCnts.bbCnt));
216    }
217    if (hfuzz->dynFileMethod & _HF_DYNFILE_CUSTOM) {
218        display_put("  - custom counter:  " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
219                    "\n", ATOMIC_GET(hfuzz->linux.hwCnts.customCnt));
220    }
221
222    if (hfuzz->dynFileMethod & _HF_DYNFILE_SOFT) {
223        uint64_t softCnt = ATOMIC_GET(hfuzz->linux.hwCnts.softCnt);
224        uint64_t softCntSec = ATOMIC_GET(hfuzz->linux.hwCnts.softCntSec);
225        display_put("  - functions seen:  " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
226                    ", secondary cnt: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET "\n",
227                    softCnt, softCntSec);
228    }
229
230    /* Sanitizer coverage specific counters */
231    if (hfuzz->useSanCov) {
232        uint64_t hitBB = ATOMIC_GET(hfuzz->sanCovCnts.hitBBCnt);
233        uint64_t totalBB = ATOMIC_GET(hfuzz->sanCovCnts.totalBBCnt);
234        float covPer = totalBB ? (((float)hitBB * 100) / totalBB) : 0.0;
235        display_put("  - total hit #bb:   " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
236                    " (coverage " ESC_BOLD "%.2f%%" ESC_RESET ")\n", hitBB, covPer);
237        display_put("  - total #dso:      " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
238                    " (instrumented only)\n", ATOMIC_GET(hfuzz->sanCovCnts.iDsoCnt));
239        display_put("  - discovered #bb:  " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
240                    " (new from input seed)\n", ATOMIC_GET(hfuzz->sanCovCnts.newBBCnt));
241        display_put("  - crashes:         " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET
242                    "\n", ATOMIC_GET(hfuzz->sanCovCnts.crashesCnt));
243    }
244    display_put("==================================| LOGS |====================================\n");
245}
246
247extern void display_display(honggfuzz_t * hfuzz)
248{
249    display_displayLocked(hfuzz);
250}
251