display.c revision 0f196511922acd2876431274f7fad363dbf3abbe
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[2J" 40#define ESC_TERM_RESET "\033c" 41#define ESC_NAV(x,y) "\033["#x";"#y"H" 42#define ESC_BOLD "\033[1m" 43#define ESC_RED "\033[31m" 44#define ESC_RESET "\033[0m" 45#define ESC_SCROLL(x,y) "\033["#x";"#y"r" 46#define ESC_SCROLL_DISABLE "\033[?7h" 47 48#if defined(_HF_ARCH_LINUX) 49#define _HF_MONETARY_MOD "'" 50#else 51#define _HF_MONETARY_MOD "" 52#endif 53 54static void display_put(const char *fmt, ...) 55{ 56 va_list args; 57 va_start(args, fmt); 58 vdprintf(logFd(), fmt, args); 59 va_end(args); 60} 61 62static void display_printKMG(uint64_t val) 63{ 64 if (val >= 1000000000UL) { 65 display_put(" [%.2lfG]", (double)val / 1000000000.0); 66 } else if (val >= 1000000UL) { 67 display_put(" [%.2lfM]", (double)val / 1000000.0); 68 } else if (val >= 1000UL) { 69 display_put(" [%.2lfk]", (double)val / 1000.0); 70 } 71} 72 73static unsigned getCpuUse(long num_cpu) 74{ 75 static uint64_t prevIdleT = 0UL; 76 77 FILE *f = fopen("/proc/stat", "re"); 78 if (f == NULL) { 79 return 0; 80 } 81 defer { 82 fclose(f); 83 }; 84 uint64_t userT, niceT, systemT, idleT; 85 if (fscanf 86 (f, "cpu %" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &userT, &niceT, &systemT, 87 &idleT) != 4) { 88 LOG_W("fscanf('/proc/stat') != 4"); 89 return 0; 90 } 91 92 if (prevIdleT == 0UL) { 93 prevIdleT = idleT; 94 return 0; 95 } 96 97 uint64_t cpuUse = (num_cpu * sysconf(_SC_CLK_TCK)) - (idleT - prevIdleT); 98 prevIdleT = idleT; 99 return cpuUse * 100 / sysconf(_SC_CLK_TCK); 100} 101 102static void display_displayLocked(honggfuzz_t * hfuzz) 103{ 104 static bool firstDisplay = true; 105 if (firstDisplay) { 106 display_put("%s", ESC_CLEAR); 107 firstDisplay = false; 108 } 109 110 unsigned long elapsed_second = (unsigned long)(time(NULL) - hfuzz->timeStart); 111 unsigned int day, hour, min, second; 112 char time_elapsed_str[64]; 113 if (elapsed_second < 24 * 3600) { 114 hour = elapsed_second / 3600; 115 min = (elapsed_second - 3600 * hour) / 60; 116 second = elapsed_second - hour * 3600 - min * 60; 117 snprintf(time_elapsed_str, sizeof(time_elapsed_str), "%u hrs %u min %u sec", hour, 118 min, second); 119 } else { 120 day = elapsed_second / 24 / 3600; 121 elapsed_second = elapsed_second - day * 24 * 3600; 122 hour = elapsed_second / 3600; 123 min = (elapsed_second - 3600 * hour) / 60; 124 second = elapsed_second - hour * 3600 - min * 60; 125 snprintf(time_elapsed_str, sizeof(time_elapsed_str), 126 "%u days %u hrs %u min %u sec", day, hour, min, second); 127 } 128 129 size_t curr_exec_cnt = ATOMIC_GET(hfuzz->mutationsCnt); 130 /* 131 * We increase the mutation counter unconditionally in threads, but if it's 132 * above hfuzz->mutationsMax we don't really execute the fuzzing loop. 133 * Therefore at the end of fuzzing, the mutation counter might be higher 134 * than hfuzz->mutationsMax 135 */ 136 if (hfuzz->mutationsMax > 0 && curr_exec_cnt > hfuzz->mutationsMax) { 137 curr_exec_cnt = hfuzz->mutationsMax; 138 } 139 float exeProgress = 0.0f; 140 if (hfuzz->mutationsMax > 0) { 141 exeProgress = ((float)curr_exec_cnt * 100 / hfuzz->mutationsMax); 142 } 143 144 static size_t prev_exec_cnt = 0UL; 145 uintptr_t exec_per_sec = curr_exec_cnt - prev_exec_cnt; 146 prev_exec_cnt = curr_exec_cnt; 147 148 /* The lock should be acquired before any output is printed on the screen */ 149 MX_SCOPED_LOCK(logMutexGet()); 150 151 display_put("%s", ESC_NAV(1, 1)); 152 display_put("----------------------------[ " ESC_BOLD "%s v%s" ESC_RESET 153 " ]---------------------------\n", PROG_NAME, PROG_VERSION); 154 display_put(" Iterations : " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET, curr_exec_cnt); 155 display_printKMG(curr_exec_cnt); 156 if (hfuzz->mutationsMax) { 157 display_put(" (out of: " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET " [" ESC_BOLD "%.2f" 158 ESC_RESET "%%])", hfuzz->mutationsMax, exeProgress); 159 } 160 switch (ATOMIC_GET(hfuzz->state)) { 161 case _HF_STATE_STATIC: 162 display_put("\n Phase : " ESC_BOLD "Main" ESC_RESET); 163 break; 164 case _HF_STATE_DYNAMIC_PRE: 165 display_put("\n Phase : " ESC_BOLD "Dry Run (1/2)" ESC_RESET); 166 break; 167 case _HF_STATE_DYNAMIC_MAIN: 168 display_put("\n Phase : " ESC_BOLD "Dynamic Main (2/2)" ESC_RESET); 169 break; 170 default: 171 display_put("\n Phase : " ESC_BOLD "Unknown" ESC_RESET); 172 break; 173 } 174 175 char start_time_str[128]; 176 util_getLocalTime("%F %T", start_time_str, sizeof(start_time_str), hfuzz->timeStart); 177 display_put("\n Run Time : " ESC_BOLD "%s" ESC_RESET " (since: " ESC_BOLD "%s" ESC_RESET 178 ")\n", time_elapsed_str, start_time_str); 179 display_put(" Input Dir : '" ESC_BOLD "%s" ESC_RESET "' (" ESC_BOLD "% " _HF_MONETARY_MOD "zu" 180 ESC_RESET ")\n", hfuzz->inputDir != NULL ? hfuzz->inputDir : "[NONE]", 181 hfuzz->fileCnt); 182 183 if (hfuzz->linux.pid > 0) { 184 display_put(" Remote cmd : [" ESC_BOLD "%d" ESC_RESET "] '" ESC_BOLD "%s" ESC_RESET 185 "'\n", hfuzz->linux.pid, hfuzz->linux.pidCmd); 186 } else { 187 display_put(" Fuzzed Cmd : '" ESC_BOLD "%s" ESC_RESET "'\n", hfuzz->cmdline_txt); 188 } 189 190 static long num_cpu = 0; 191 if (num_cpu == 0) { 192 num_cpu = sysconf(_SC_NPROCESSORS_ONLN); 193 } 194 unsigned cpuUse = getCpuUse(num_cpu); 195 display_put(" Threads : " ESC_BOLD "%zu" ESC_RESET ", CPUs: " ESC_BOLD "%ld" ESC_RESET 196 ", CPU: " ESC_BOLD "%u" ESC_RESET "%% (" ESC_BOLD "%u" ESC_RESET "%%/CPU)\n", 197 hfuzz->threadsMax, num_cpu, cpuUse, cpuUse / num_cpu); 198 199 display_put(" Speed : " ESC_BOLD "% " _HF_MONETARY_MOD "zu" ESC_RESET "/sec" 200 " (avg: " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET ")\n", exec_per_sec, 201 elapsed_second ? (curr_exec_cnt / elapsed_second) : 0); 202 203 uint64_t crashesCnt = ATOMIC_GET(hfuzz->crashesCnt); 204 /* colored the crash count as red when exist crash */ 205 display_put(" Crashes : " ESC_BOLD "%s" "%zu" ESC_RESET " (unique: %s" ESC_BOLD "%zu" 206 ESC_RESET ", blacklist: " ESC_BOLD "%zu" ESC_RESET ", verified: " 207 ESC_BOLD "%zu" ESC_RESET ")\n", crashesCnt > 0 ? ESC_RED : "", 208 hfuzz->crashesCnt, crashesCnt > 0 ? ESC_RED : "", 209 ATOMIC_GET(hfuzz->uniqueCrashesCnt), ATOMIC_GET(hfuzz->blCrashesCnt), 210 ATOMIC_GET(hfuzz->verifiedCrashesCnt)); 211 display_put(" Timeouts : " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET " [%" 212 _HF_MONETARY_MOD "zu sec.]\n", ATOMIC_GET(hfuzz->timeoutedCnt), hfuzz->tmOut); 213 /* Feedback data sources are enabled. Start with common headers. */ 214 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE || hfuzz->useSanCov) { 215 display_put(" Corpus Size : " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET 216 ", max size (bytes): " ESC_BOLD "%" _HF_MONETARY_MOD "zu" ESC_RESET "\n", 217 hfuzz->dynfileqCnt, hfuzz->maxFileSz); 218 display_put(" Coverage :"); 219 } 220 221 /* HW perf specific counters */ 222 if (hfuzz->dynFileMethod & _HF_DYNFILE_INSTR_COUNT) { 223 display_put(" hwi: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 224 ATOMIC_GET(hfuzz->linux.hwCnts.cpuInstrCnt)); 225 } 226 if (hfuzz->dynFileMethod & _HF_DYNFILE_BRANCH_COUNT) { 227 display_put(" hwb: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 228 ATOMIC_GET(hfuzz->linux.hwCnts.cpuBranchCnt)); 229 } 230 if (hfuzz->dynFileMethod & (_HF_DYNFILE_BTS_BLOCK | _HF_DYNFILE_BTS_EDGE)) { 231 display_put(" bts: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 232 ATOMIC_GET(hfuzz->linux.hwCnts.bbCnt)); 233 } 234 if (hfuzz->dynFileMethod & _HF_DYNFILE_IPT_BLOCK) { 235 display_put(" ipt: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 236 ATOMIC_GET(hfuzz->linux.hwCnts.bbCnt)); 237 } 238 if (hfuzz->dynFileMethod & _HF_DYNFILE_SOFT) { 239 uint64_t softCntPc = ATOMIC_GET(hfuzz->linux.hwCnts.softCntPc); 240 uint64_t softCntCmp = ATOMIC_GET(hfuzz->linux.hwCnts.softCntCmp); 241 display_put(" bb: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, softCntPc); 242 display_put(" cmp: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, softCntCmp); 243 } 244 245 /* Sanitizer coverage specific counters */ 246 if (hfuzz->useSanCov) { 247 uint64_t hitBB = ATOMIC_GET(hfuzz->sanCovCnts.hitBBCnt); 248 uint64_t totalBB = ATOMIC_GET(hfuzz->sanCovCnts.totalBBCnt); 249 float covPer = totalBB ? (((float)hitBB * 100) / totalBB) : 0.0; 250 display_put(" (sancov) #bb: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET " (cov: " 251 ESC_BOLD "%.2f" ESC_RESET "%%)", hitBB, covPer); 252 display_put(" #dso: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 253 ATOMIC_GET(hfuzz->sanCovCnts.iDsoCnt)); 254 display_put(" #newbb: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 255 ATOMIC_GET(hfuzz->sanCovCnts.newBBCnt)); 256 display_put(" #crashes: " ESC_BOLD "%" _HF_MONETARY_MOD PRIu64 ESC_RESET, 257 ATOMIC_GET(hfuzz->sanCovCnts.crashesCnt)); 258 } 259 display_put("\n-----------------------------------[ " ESC_BOLD "LOGS" ESC_RESET 260 " ]-----------------------------------\n"); 261 display_put(ESC_SCROLL(14, 999) ESC_NAV(999, 1)); 262} 263 264extern void display_display(honggfuzz_t * hfuzz) 265{ 266 if (logIsTTY() == false) { 267 return; 268 } 269 display_displayLocked(hfuzz); 270} 271 272extern void display_init(void) 273{ 274 display_put(ESC_NAV(999, 1)); 275} 276 277extern void display_fini(void) 278{ 279 display_put(ESC_SCROLL(1, 999) ESC_NAV(999, 1)); 280} 281