xref: /aosp_15_r20/external/AFLplusplus/afl-plot (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1#!/bin/sh
2#
3# american fuzzy lop++ - Advanced Persistent Graphing
4# -------------------------------------------------
5#
6# Originally written by Michal Zalewski
7# Based on a design & prototype by Michael Rash.
8#
9# Copyright 2014, 2015 Google Inc. All rights reserved.
10#
11# Licensed under the Apache License, Version 2.0 (the "License");
12# you may not use this file except in compliance with the License.
13# You may obtain a copy of the License at:
14#
15#   https://www.apache.org/licenses/LICENSE-2.0
16#
17
18get_abs_path() {
19  echo $(cd "`dirname "$1"`" && pwd)/"`basename "$1"`"
20}
21
22echo "progress plotting utility for afl-fuzz by Michal Zalewski"
23echo
24
25GRAPHICAL="0"
26
27if [ "$1"  = "-g" ] || [ "$1" = "--graphical" ]; then
28GRAPHICAL="1"
29shift
30fi
31
32if [ "$#" != "2" ]; then
33
34  cat 1>&2 <<_EOF_
35$0 [ -g | --graphical ] afl_state_dir graph_output_dir
36
37This program generates gnuplot images from afl-fuzz output data.
38
39Usage:
40
41    afl_state_dir       should point to an existing state directory for any
42                        active or stopped instance of afl-fuzz
43    graph_output_dir    should point to an empty directory where this
44                        tool can write the resulting plots to
45    -g, --graphical     (optional) display the plots in a graphical window
46                        (you should have built afl-plot-ui to use this option)
47
48The program will put index.html and three PNG images in the output directory;
49you should be able to view it with any web browser of your choice.
50_EOF_
51
52  exit 1
53
54fi
55
56inputdir=`get_abs_path "$1"`
57outputdir=`get_abs_path "$2"`
58
59#if [ "$AFL_ALLOW_TMP" = "" ]; then
60#
61#  echo "$inputdir" | grep -qE '^(/var)?/tmp/'
62#  T1="$?"
63#
64#  echo "$outputdir" | grep -qE '^(/var)?/tmp/'
65#  T2="$?"
66#
67#  if [ "$T1" = "0" -o "$T2" = "0" ]; then
68#
69#    echo "[-] Error: this script shouldn't be used with shared /tmp directories." 1>&2
70#    exit 1
71#
72#  fi
73#
74#fi
75
76if [ ! -f "$inputdir/plot_data" ]; then
77
78  if [ -f "$inputdir/default/plot_data" ]; then
79
80    echo "[-] Error: input directory is not valid (missing 'plot_data'), likely you mean $inputdir/default?" 1>&2
81    exit 1
82
83  else
84
85    echo "[-] Error: input directory is not valid (missing 'plot_data')." 1>&2
86    exit 1
87
88  fi
89
90fi
91
92LINES=`cat "$inputdir/plot_data" | wc -l`
93
94if [ "$LINES" -lt 3 ]; then
95
96  echo "[-] Error: plot_data carries too little data, let it run longer." 1>&2
97  exit 1
98
99fi
100
101BANNER="`cat "$inputdir/fuzzer_stats" 2> /dev/null | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`"
102
103test "$BANNER" = "" && BANNER="(none)"
104
105GNUPLOT=`command -v gnuplot 2>/dev/null`
106
107if [ "$GNUPLOT" = "" ]; then
108
109  echo "[-] Error: can't find 'gnuplot' in your \$PATH." 1>&2
110  exit 1
111
112fi
113
114mkdir "$outputdir" 2>/dev/null
115
116if [ ! -d "$outputdir" ]; then
117
118  echo "[-] Error: unable to create the output directory - pick another location." 1>&2
119  exit 1
120
121fi
122
123rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png"
124mv -f "$outputdir/index.html" "$outputdir/index.html.orig" 2>/dev/null
125
126GNUPLOT_SETUP="
127#set xdata time
128#set timefmt '%s'
129#set format x \"%b %d\n%H:%M\"
130set tics font 'small'
131unset mxtics
132unset mytics
133
134set grid xtics linetype 0 linecolor rgb '#e0e0e0'
135set grid ytics linetype 0 linecolor rgb '#e0e0e0'
136set border linecolor rgb '#50c0f0'
137set tics textcolor rgb '#000000'
138set key outside
139
140set autoscale xfixmin
141set autoscale xfixmax
142
143set xlabel \"relative time in seconds\" font \"small\"
144"
145
146PLOT_HF="
147set terminal png truecolor enhanced size 1000,300 butt
148set output '$outputdir/high_freq.png'
149
150$GNUPLOT_SETUP
151
152plot '$inputdir/plot_data' using 1:4 with filledcurve x1 title 'corpus count' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\
153     '' using 1:3 with filledcurve x1 title 'current item' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\
154     '' using 1:5 with lines title 'pending items' linecolor rgb '#0090ff' linewidth 3, \\
155     '' using 1:6 with lines title 'pending favs' linecolor rgb '#c00080' linewidth 3, \\
156     '' using 1:2 with lines title 'cycles done' linecolor rgb '#c000f0' linewidth 3
157"
158
159PLOT_LF="
160set terminal png truecolor enhanced size 1000,200 butt
161set output '$outputdir/low_freq.png'
162
163$GNUPLOT_SETUP
164
165plot '$inputdir/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\
166     '' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\
167     '' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\
168     '' using 1:10 with lines title 'levels' linecolor rgb '#0090ff' linewidth 3
169"
170
171PLOT_ES="
172set terminal png truecolor enhanced size 1000,200 butt
173set output '$outputdir/exec_speed.png'
174
175$GNUPLOT_SETUP
176
177plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
178     '$inputdir/plot_data' using 1:11 with lines title '    execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
179"
180
181PLOT_EG="
182set terminal png truecolor enhanced size 1000,300 butt
183set output '$outputdir/edges.png'
184
185$GNUPLOT_SETUP
186
187plot '$inputdir/plot_data' using 1:13 with lines title '        edges' linecolor rgb '#0090ff' linewidth 3
188"
189
190if [ "$#" = "2" ] && [ "$GRAPHICAL" = "1" ]; then
191
192afl-plot-ui -h > /dev/null 2>&1
193
194if [ "$?" != "0" ]; then
195
196cat 1>&2 <<_EOF_
197You do not seem to have the afl-plot-ui utility installed. If you have installed afl-plot-ui, make sure the afl-plot-ui executable is in your PATH.
198If you are still facing any problems, please open an issue at https://github.com/AFLplusplus/AFLplusplus/issues.
199
200No plots have been generated. Please rerun without the "-g" or "--graphical" flag to generate the plots.
201_EOF_
202
203exit 1
204
205fi
206
207rm -rf "$outputdir/.tmp"
208mkdir -p "$outputdir/.tmp"
209mkfifo "$outputdir/.tmp/win_ids" || exit 1
210
211afl-plot-ui > "$outputdir/.tmp/win_ids" &
212W_IDS=$(cat "$outputdir/.tmp/win_ids")
213
214rm -rf "$outputdir/.tmp"
215
216W_ID1=$(echo "$W_IDS" | head -n 1)
217W_ID2=$(echo "$W_IDS" | head -n 2 | tail -n 1)
218W_ID3=$(echo "$W_IDS" | head -n 3 | tail -n 1)
219W_ID4=$(echo "$W_IDS" | tail -n 1)
220
221echo "[*] Generating plots..."
222
223(
224
225cat << _EOF_
226
227$PLOT_HF
228set term x11 window "$W_ID3"
229set output
230replot
231pause mouse close
232
233_EOF_
234
235) | gnuplot 2> /dev/null &
236
237(
238
239cat << _EOF_
240
241$PLOT_LF
242set term x11 window "$W_ID4"
243set output
244replot
245pause mouse close
246
247_EOF_
248
249) | gnuplot 2> /dev/null &
250
251(
252
253cat << _EOF_
254
255$PLOT_ES
256set term x11 window "$W_ID2"
257set output
258replot
259pause mouse close
260
261_EOF_
262
263) | gnuplot 2> /dev/null &
264
265(
266
267cat << _EOF_
268
269$PLOT_EG
270set term x11 window "$W_ID1"
271set output
272replot
273pause mouse close
274
275_EOF_
276
277) | gnuplot 2> /dev/null &
278
279sleep 1
280
281else
282
283echo "[*] Generating plots..."
284
285(
286
287cat << _EOF_
288
289$PLOT_HF
290
291$PLOT_LF
292
293$PLOT_ES
294
295$PLOT_EG
296
297_EOF_
298
299) | gnuplot || echo "Note: if you see errors concerning 'unknown or ambiguous terminal type' then you need to use a gnuplot that has png support compiled in."
300
301echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot -h\" to know more."
302
303fi
304
305if [ ! -s "$outputdir/exec_speed.png" ]; then
306
307  echo "[-] Error: something went wrong! Perhaps you have an ancient version of gnuplot?" 1>&2
308  exit 1
309
310fi
311
312echo "[*] Generating index.html..."
313
314cat >"$outputdir/index.html" <<_EOF_
315<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
316<tr><td style="width: 18ex"><b>Banner:</b></td><td>$BANNER</td></tr>
317<tr><td><b>Directory:</b></td><td>$inputdir</td></tr>
318<tr><td><b>Generated on:</b></td><td>`date`</td></tr>
319</table>
320<p>
321<img src="edges.png" width=1000 height=300>
322<img src="high_freq.png" width=1000 height=300><p>
323<img src="low_freq.png" width=1000 height=200><p>
324<img src="exec_speed.png" width=1000 height=200>
325
326_EOF_
327
328# Make it easy to remotely view results when outputting directly to a directory
329# served by Apache or other HTTP daemon. Since the plots aren't horribly
330# sensitive, this seems like a reasonable trade-off.
331
332chmod 755 "$outputdir"
333chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" "$outputdir/index.html"
334
335echo "[+] All done - enjoy your charts!"
336
337exit 0
338