"Fossies" - the Fresh Open Source Software Archive

Member "honggfuzz-2.2/display.c" (23 Apr 2020, 12683 Bytes) of package /linux/privat/honggfuzz-2.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "display.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1_vs_2.2.

    1 /*
    2  *
    3  * honggfuzz - display statistics
    4  * -----------------------------------------
    5  *
    6  * Author: Robert Swiecki <swiecki@google.com>
    7  *
    8  * Copyright 2010-2018 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 "display.h"
   27 
   28 #include <errno.h>
   29 #include <inttypes.h>
   30 #include <math.h>
   31 #include <stdarg.h>
   32 #include <stdio.h>
   33 #include <stdlib.h>
   34 #include <string.h>
   35 #include <unistd.h>
   36 
   37 #include "libhfcommon/common.h"
   38 #include "libhfcommon/log.h"
   39 #include "libhfcommon/util.h"
   40 
   41 #define ESC_CLEAR_ALL "\033[2J"
   42 #define ESC_CLEAR_LINE "\033[2K"
   43 #define ESC_CLEAR_ABOVE "\033[1J"
   44 #define ESC_TERM_RESET "\033c"
   45 #define ESC_NAV(x, y) "\033[" #x ";" #y "H"
   46 #define ESC_BOLD "\033[1m"
   47 #define ESC_RED "\033[31m"
   48 #define ESC_RESET "\033[0m"
   49 #define ESC_SCROLL_REGION(x, y) "\033[" #x ";" #y "r"
   50 #define ESC_SCROLL_DISABLE "\033[?7h"
   51 #define ESC_SCROLL_RESET "\033[r"
   52 #define ESC_NAV_DOWN(x) "\033[" #x "B"
   53 #define ESC_NAV_HORIZ(x) "\033[" #x "G"
   54 #define ESC_RESET_SETTINGS "\033[!p"
   55 
   56 static char displayBuf[1024 * 1024];
   57 static void display_start(void) {
   58     memset(displayBuf, '\0', sizeof(displayBuf));
   59 }
   60 
   61 static void display_stop(void) {
   62     TEMP_FAILURE_RETRY(write(logFd(), displayBuf, strlen(displayBuf)));
   63 }
   64 
   65 __attribute__((format(printf, 1, 2))) static void display_put(const char* fmt, ...) {
   66     va_list args;
   67     va_start(args, fmt);
   68     util_vssnprintf(displayBuf, sizeof(displayBuf), fmt, args);
   69     va_end(args);
   70 }
   71 
   72 static void display_imm(const char* str) {
   73     TEMP_FAILURE_RETRY(write(logFd(), str, strlen(str)));
   74 }
   75 
   76 static void display_printKMG(uint64_t val) {
   77     if (val >= 1000000000000ULL) {
   78         display_put(" [%.02LfT]", (long double)val / 1000000000.0L);
   79     } else if (val >= 1000000000UL) {
   80         display_put(" [%.02LfG]", (long double)val / 1000000000.0L);
   81     } else if (val >= 1000000UL) {
   82         display_put(" [%.02LfM]", (long double)val / 1000000.0L);
   83     } else if (val >= 1000UL) {
   84         display_put(" [%.02Lfk]", (long double)val / 1000.0L);
   85     }
   86 }
   87 
   88 static unsigned getCpuUse(int numCpus) {
   89     static uint64_t prevUserT = 0UL;
   90     static uint64_t prevNiceT = 0UL;
   91     static uint64_t prevSystemT = 0UL;
   92     static uint64_t prevIdleT = 0UL;
   93 
   94     FILE* f = fopen("/proc/stat", "re");
   95     if (f == NULL) {
   96         return 0;
   97     }
   98     defer {
   99         fclose(f);
  100     };
  101     uint64_t userT, niceT, systemT, idleT;
  102     if (fscanf(f, "cpu  %" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &userT, &niceT, &systemT,
  103             &idleT) != 4) {
  104         LOG_W("fscanf('/proc/stat') != 4");
  105         return 0;
  106     }
  107 
  108     uint64_t userCycles = (userT - prevUserT);
  109     uint64_t niceCycles = (niceT - prevNiceT);
  110     uint64_t systemCycles = (systemT - prevSystemT);
  111     uint64_t idleCycles = (idleT - prevIdleT);
  112 
  113     prevUserT = userT;
  114     prevNiceT = niceT;
  115     prevSystemT = systemT;
  116     prevIdleT = idleT;
  117 
  118     uint64_t allCycles = userCycles + niceCycles + systemCycles + idleCycles;
  119     if (allCycles == 0) {
  120         return 0;
  121     }
  122 
  123     return ((userCycles + niceCycles + systemCycles) * numCpus * 100) / (allCycles);
  124 }
  125 
  126 static void getDuration(time_t elapsed_second, char* buf, size_t bufSz) {
  127     if (elapsed_second < 0) {
  128         snprintf(buf, bufSz, "----");
  129         return;
  130     }
  131 
  132     unsigned int day, hour, min, second;
  133     day = elapsed_second / 24 / 3600;
  134     elapsed_second = elapsed_second - day * 24 * 3600;
  135     hour = elapsed_second / 3600;
  136     min = (elapsed_second - 3600 * hour) / 60;
  137     second = elapsed_second - hour * 3600 - min * 60;
  138     snprintf(buf, bufSz, "%u days %02u hrs %02u mins %02u secs", day, hour, min, second);
  139 }
  140 
  141 void display_createTargetStr(honggfuzz_t* hfuzz) {
  142     if (!hfuzz->exe.cmdline[0]) {
  143         LOG_W("Your fuzzed binary is not specified");
  144         snprintf(hfuzz->display.cmdline_txt, sizeof(hfuzz->display.cmdline_txt), "[EMPTY]");
  145         return;
  146     }
  147 
  148     static char tmpstr[1024 * 128] = {0};
  149     snprintf(tmpstr, sizeof(tmpstr), "%s", hfuzz->exe.cmdline[0]);
  150     for (int i = 1; i < hfuzz->exe.argc; i++) {
  151         util_ssnprintf(tmpstr, sizeof(tmpstr), " %s", hfuzz->exe.cmdline[i]);
  152     }
  153 
  154     size_t len = strlen(tmpstr);
  155     if (len <= (sizeof(hfuzz->display.cmdline_txt) - 1)) {
  156         snprintf(hfuzz->display.cmdline_txt, sizeof(hfuzz->display.cmdline_txt), "%s", tmpstr);
  157         return;
  158     }
  159 
  160     snprintf(hfuzz->display.cmdline_txt, sizeof(hfuzz->display.cmdline_txt), "%.32s.....%s", tmpstr,
  161         &tmpstr[len - 27]);
  162 }
  163 
  164 void display_display(honggfuzz_t* hfuzz) {
  165     if (logIsTTY() == false) {
  166         return;
  167     }
  168 
  169     const time_t curr_sec = time(NULL);
  170     const time_t elapsed_sec = curr_sec - hfuzz->timing.timeStart;
  171     const int64_t curr_time_usecs = util_timeNowUSecs();
  172     const int64_t elapsed_usecs = curr_time_usecs - hfuzz->display.lastDisplayUSecs;
  173     hfuzz->display.lastDisplayUSecs = curr_time_usecs;
  174 
  175     char lastCovStr[64];
  176     getDuration(curr_sec - ATOMIC_GET(hfuzz->timing.lastCovUpdate), lastCovStr, sizeof(lastCovStr));
  177     char timeStr[64];
  178     if (ATOMIC_GET(hfuzz->timing.runEndTime)) {
  179         getDuration(ATOMIC_GET(hfuzz->timing.runEndTime) - curr_sec, timeStr, sizeof(timeStr));
  180     } else {
  181         getDuration(elapsed_sec, timeStr, sizeof(timeStr));
  182     }
  183 
  184     size_t curr_exec_cnt = ATOMIC_GET(hfuzz->cnts.mutationsCnt);
  185     /*
  186      * We increase the mutation counter unconditionally in threads, but if it's
  187      * above hfuzz->mutationsMax we don't really execute the fuzzing loop.
  188      * Therefore at the end of fuzzing, the mutation counter might be higher
  189      * than hfuzz->mutationsMax
  190      */
  191     if (hfuzz->mutate.mutationsMax > 0 && curr_exec_cnt > hfuzz->mutate.mutationsMax) {
  192         curr_exec_cnt = hfuzz->mutate.mutationsMax;
  193     }
  194     int exeProgress = 0;
  195     if (hfuzz->mutate.mutationsMax > 0) {
  196         exeProgress = (curr_exec_cnt * 100) / hfuzz->mutate.mutationsMax;
  197     }
  198 
  199     static size_t prev_exec_cnt = 0UL;
  200     size_t exec_per_usecs =
  201         elapsed_usecs ? ((curr_exec_cnt - prev_exec_cnt) * 1000000) / elapsed_usecs : 0;
  202     prev_exec_cnt = curr_exec_cnt;
  203 
  204     display_start();
  205 
  206     display_put(ESC_NAV(13, 1) ESC_CLEAR_ABOVE ESC_NAV(1, 1));
  207     display_put("------------------------[" ESC_BOLD "%31s " ESC_RESET "]----------------------\n",
  208         timeStr);
  209     display_put("  Iterations : " ESC_BOLD "%" _HF_NONMON_SEP "zu" ESC_RESET, curr_exec_cnt);
  210     display_printKMG(curr_exec_cnt);
  211     if (hfuzz->mutate.mutationsMax) {
  212         display_put(" (out of: " ESC_BOLD "%" _HF_NONMON_SEP "zu" ESC_RESET " [%d%%])",
  213             hfuzz->mutate.mutationsMax, exeProgress);
  214     }
  215     switch (ATOMIC_GET(hfuzz->feedback.state)) {
  216         case _HF_STATE_STATIC:
  217             display_put("\n        Mode : " ESC_BOLD "Static" ESC_RESET "\n");
  218             break;
  219         case _HF_STATE_DYNAMIC_DRY_RUN: {
  220             if (ATOMIC_GET(hfuzz->cfg.switchingToFDM)) {
  221                 display_put("\n  Mode [2/3] : " ESC_BOLD
  222                             "Switching to the Feedback Driven Mode" ESC_RESET " [%zu/%zu]\n",
  223                     hfuzz->io.testedFileCnt, hfuzz->io.fileCnt);
  224             } else {
  225                 display_put("\n  Mode [1/3] : " ESC_BOLD "Feedback Driven Dry Run" ESC_RESET
  226                             " [%zu/%zu]\n",
  227                     hfuzz->io.testedFileCnt, hfuzz->io.fileCnt);
  228             }
  229         } break;
  230         case _HF_STATE_DYNAMIC_MAIN:
  231             display_put("\n  Mode [3/3] : " ESC_BOLD "Feedback Driven Mode" ESC_RESET "\n");
  232             break;
  233         case _HF_STATE_DYNAMIC_MINIMIZE:
  234             display_put("\n  Mode [3/3] : " ESC_BOLD "Corpus Minimization" ESC_RESET "\n");
  235             break;
  236         default:
  237             display_put("\n        Mode : " ESC_BOLD "Unknown" ESC_RESET "\n");
  238             break;
  239     }
  240     display_put("      Target : " ESC_BOLD "%s" ESC_RESET "\n", hfuzz->display.cmdline_txt);
  241 
  242     static long num_cpu = 0;
  243     if (num_cpu == 0) {
  244         num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
  245     }
  246     if (num_cpu <= 0) {
  247         num_cpu = 1;
  248     }
  249     unsigned cpuUse = getCpuUse(num_cpu);
  250     display_put("     Threads : " ESC_BOLD "%zu" ESC_RESET ", CPUs: " ESC_BOLD "%ld" ESC_RESET
  251                 ", CPU%%: " ESC_BOLD "%u" ESC_RESET "%% [" ESC_BOLD "%lu" ESC_RESET "%%/CPU]\n",
  252         hfuzz->threads.threadsMax, num_cpu, cpuUse, cpuUse / num_cpu);
  253 
  254     size_t tot_exec_per_sec = elapsed_sec ? (curr_exec_cnt / elapsed_sec) : 0;
  255     display_put("       Speed : " ESC_BOLD "%" _HF_NONMON_SEP "zu" ESC_RESET "/sec [avg: " ESC_BOLD
  256                 "%" _HF_NONMON_SEP "zu" ESC_RESET "]\n",
  257         exec_per_usecs, tot_exec_per_sec);
  258 
  259     uint64_t crashesCnt = ATOMIC_GET(hfuzz->cnts.crashesCnt);
  260     /* colored the crash count as red when exist crash */
  261     display_put("     Crashes : " ESC_BOLD "%s"
  262                 "%zu" ESC_RESET " [unique: %s" ESC_BOLD "%zu" ESC_RESET ", blacklist: " ESC_BOLD
  263                 "%zu" ESC_RESET ", verified: " ESC_BOLD "%zu" ESC_RESET "]\n",
  264         crashesCnt > 0 ? ESC_RED : "", hfuzz->cnts.crashesCnt, crashesCnt > 0 ? ESC_RED : "",
  265         ATOMIC_GET(hfuzz->cnts.uniqueCrashesCnt), ATOMIC_GET(hfuzz->cnts.blCrashesCnt),
  266         ATOMIC_GET(hfuzz->cnts.verifiedCrashesCnt));
  267     display_put("    Timeouts : " ESC_BOLD "%" _HF_NONMON_SEP "zu" ESC_RESET " [%lu sec]\n",
  268         ATOMIC_GET(hfuzz->cnts.timeoutedCnt), (unsigned long)hfuzz->timing.tmOut);
  269     /* Feedback data sources. Common headers. */
  270     display_put(" Corpus Size : " ESC_BOLD "%" _HF_NONMON_SEP "zu" ESC_RESET ", max: " ESC_BOLD
  271                 "%" _HF_NONMON_SEP "zu" ESC_RESET " bytes, init: " ESC_BOLD "%" _HF_NONMON_SEP
  272                 "zu" ESC_RESET " files\n",
  273         hfuzz->io.dynfileqCnt, hfuzz->mutate.maxInputSz, ATOMIC_GET(hfuzz->io.fileCnt));
  274     display_put("  Cov Update : " ESC_BOLD "%s" ESC_RESET " ago\n" ESC_RESET, lastCovStr);
  275     display_put("    Coverage :");
  276 
  277     /* HW perf specific counters */
  278     if (hfuzz->feedback.dynFileMethod == 0) {
  279         display_put(" [none]");
  280     }
  281     if (hfuzz->feedback.dynFileMethod & _HF_DYNFILE_INSTR_COUNT) {
  282         display_put(" hwi: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET,
  283             ATOMIC_GET(hfuzz->feedback.hwCnts.cpuInstrCnt));
  284     }
  285     if (hfuzz->feedback.dynFileMethod & _HF_DYNFILE_BRANCH_COUNT) {
  286         display_put(" hwb: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET,
  287             ATOMIC_GET(hfuzz->feedback.hwCnts.cpuBranchCnt));
  288     }
  289     if (hfuzz->feedback.dynFileMethod & _HF_DYNFILE_BTS_EDGE) {
  290         display_put(" bts: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET,
  291             ATOMIC_GET(hfuzz->feedback.hwCnts.bbCnt));
  292     }
  293     if (hfuzz->feedback.dynFileMethod & _HF_DYNFILE_IPT_BLOCK) {
  294         display_put(" ipt: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET,
  295             ATOMIC_GET(hfuzz->feedback.hwCnts.bbCnt));
  296     }
  297     if (hfuzz->feedback.dynFileMethod & _HF_DYNFILE_SOFT) {
  298         uint64_t softCntPc = ATOMIC_GET(hfuzz->feedback.hwCnts.softCntPc);
  299         uint64_t softCntEdge = ATOMIC_GET(hfuzz->feedback.hwCnts.softCntEdge);
  300         uint64_t softCntCmp = ATOMIC_GET(hfuzz->feedback.hwCnts.softCntCmp);
  301         uint64_t guardNb = ATOMIC_GET(hfuzz->feedback.covFeedbackMap->guardNb);
  302         display_put(" edge: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET "/"
  303                     "%" _HF_NONMON_SEP PRIu64 " [%" PRId64 "%%]",
  304             softCntEdge, guardNb, guardNb ? ((softCntEdge * 100) / guardNb) : 0);
  305         display_put(" pc: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET, softCntPc);
  306         display_put(" cmp: " ESC_BOLD "%" _HF_NONMON_SEP PRIu64 ESC_RESET, softCntCmp);
  307     }
  308 
  309     display_put("\n---------------------------------- [ " ESC_BOLD "LOGS" ESC_RESET
  310                 " ] ------------------/ " ESC_BOLD "%s %s " ESC_RESET "/-",
  311         PROG_NAME, PROG_VERSION);
  312     display_put(ESC_SCROLL_REGION(13, ) ESC_NAV_HORIZ(1) ESC_NAV_DOWN(500));
  313 
  314     MX_SCOPED_LOCK(logMutexGet());
  315     display_stop();
  316 }
  317 
  318 void display_fini(void) {
  319     display_imm(ESC_SCROLL_RESET ESC_NAV_DOWN(500));
  320 }
  321 
  322 void display_clear(void) {
  323     display_imm(ESC_CLEAR_ALL);
  324     display_imm(ESC_NAV_DOWN(500));
  325 }
  326 
  327 void display_init(void) {
  328     atexit(display_fini);
  329     display_clear();
  330 }