about summary refs log tree commit diff
path: root/qemu_mode/patches/afl-qemu-cpu-translate-inl.h
blob: 3d3c1b6b1e7a0a14cb1e9e898b397875af5771f7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
   american fuzzy lop++ - high-performance binary-only instrumentation
   -------------------------------------------------------------------

   Originally written by Andrew Griffiths <agriffiths@google.com> and
                         Michal Zalewski <lcamtuf@google.com>

   TCG instrumentation and block chaining support by Andrea Biondo
                                      <andrea.biondo965@gmail.com>

   QEMU 3.1.0 port, TCG thread-safety, CompareCoverage and NeverZero
   counters by Andrea Fioraldi <andreafioraldi@gmail.com>

   Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
   Copyright 2019 AFLplusplus Project. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at:

     http://www.apache.org/licenses/LICENSE-2.0

   This code is a shim patched into the separately-distributed source
   code of QEMU 3.1.0. It leverages the built-in QEMU tracing functionality
   to implement AFL-style instrumentation and to take care of the remaining
   parts of the AFL fork server logic.

   The resulting QEMU binary is essentially a standalone instrumentation
   tool; for an example of how to leverage it for other purposes, you can
   have a look at afl-showmap.c.

 */

#include "afl-qemu-common.h"
#include "tcg.h"
#include "tcg-op.h"

/* Declared in afl-qemu-cpu-inl.h */
extern unsigned char *afl_area_ptr;
extern unsigned int   afl_inst_rms;
extern abi_ulong      afl_start_code, afl_end_code;
extern u8             afl_compcov_level;

void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
                                  TCGv_i64 arg1, TCGv_i64 arg2);

static void afl_compcov_log_16(target_ulong cur_loc, target_ulong arg1,
                               target_ulong arg2) {

  if ((arg1 & 0xff) == (arg2 & 0xff)) { INC_AFL_AREA(cur_loc); }

}

static void afl_compcov_log_32(target_ulong cur_loc, target_ulong arg1,
                               target_ulong arg2) {

  if ((arg1 & 0xff) == (arg2 & 0xff)) {

    INC_AFL_AREA(cur_loc);
    if ((arg1 & 0xffff) == (arg2 & 0xffff)) {

      INC_AFL_AREA(cur_loc + 1);
      if ((arg1 & 0xffffff) == (arg2 & 0xffffff)) { INC_AFL_AREA(cur_loc + 2); }

    }

  }

}

static void afl_compcov_log_64(target_ulong cur_loc, target_ulong arg1,
                               target_ulong arg2) {

  if ((arg1 & 0xff) == (arg2 & 0xff)) {

    INC_AFL_AREA(cur_loc);
    if ((arg1 & 0xffff) == (arg2 & 0xffff)) {

      INC_AFL_AREA(cur_loc + 1);
      if ((arg1 & 0xffffff) == (arg2 & 0xffffff)) {

        INC_AFL_AREA(cur_loc + 2);
        if ((arg1 & 0xffffffff) == (arg2 & 0xffffffff)) {

          INC_AFL_AREA(cur_loc + 3);
          if ((arg1 & 0xffffffffff) == (arg2 & 0xffffffffff)) {

            INC_AFL_AREA(cur_loc + 4);
            if ((arg1 & 0xffffffffffff) == (arg2 & 0xffffffffffff)) {

              INC_AFL_AREA(cur_loc + 5);
              if ((arg1 & 0xffffffffffffff) == (arg2 & 0xffffffffffffff)) {

                INC_AFL_AREA(cur_loc + 6);

              }

            }

          }

        }

      }

    }

  }

}

static void afl_gen_compcov(target_ulong cur_loc, TCGv_i64 arg1, TCGv_i64 arg2,
                            TCGMemOp ot, int is_imm) {

  void *func;

  if (!afl_compcov_level || cur_loc > afl_end_code || cur_loc < afl_start_code)
    return;

  if (!is_imm && afl_compcov_level < 2) return;

  switch (ot) {

    case MO_64: func = &afl_compcov_log_64; break;
    case MO_32: func = &afl_compcov_log_32; break;
    case MO_16: func = &afl_compcov_log_16; break;
    default: return;

  }

  cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
  cur_loc &= MAP_SIZE - 7;

  if (cur_loc >= afl_inst_rms) return;

  tcg_gen_afl_compcov_log_call(func, cur_loc, arg1, arg2);

}