blob: ace45279ae0e59acf3de704943e5a8feabbfdef1 [file] [log] [blame]
Kostya Serebryany22526252015-05-11 21:16:27 +00001//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===//
Kostya Serebryany16d03bd2015-03-30 22:09:51 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Kostya Serebryany4820cc92016-10-04 06:08:46 +00009// Data tracing.
Kostya Serebryany16d03bd2015-03-30 22:09:51 +000010//===----------------------------------------------------------------------===//
11
Kostya Serebryany16d03bd2015-03-30 22:09:51 +000012#include "FuzzerInternal.h"
Kostya Serebryany6f5a8042016-09-21 01:50:50 +000013#include "FuzzerDictionary.h"
14#include "FuzzerMutate.h"
15#include "FuzzerRandom.h"
Kostya Serebryanyab73c692016-09-23 00:46:18 +000016#include "FuzzerTracePC.h"
Kostya Serebryany16d03bd2015-03-30 22:09:51 +000017
Kostya Serebryanybeb24c32015-05-07 21:02:11 +000018#include <algorithm>
Kostya Serebryany16d03bd2015-03-30 22:09:51 +000019#include <cstring>
Kostya Serebryany226b7342016-01-06 00:03:35 +000020#include <thread>
Kostya Serebryany859e86d2016-01-12 02:08:37 +000021#include <map>
Kostya Serebryanyc135b552016-07-15 23:27:19 +000022#include <set>
Kostya Serebryany16d03bd2015-03-30 22:09:51 +000023
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +000024namespace fuzzer {
25
Kostya Serebryanybeb24c32015-05-07 21:02:11 +000026// For now, very simple: put Size bytes of Data at position Pos.
27struct TraceBasedMutation {
Kostya Serebryany476f0ce2016-01-16 03:53:32 +000028 uint32_t Pos;
29 Word W;
Kostya Serebryanybeb24c32015-05-07 21:02:11 +000030};
31
Kostya Serebryanyae5b9562016-01-15 06:24:05 +000032// Declared as static globals for faster checks inside the hooks.
Kostya Serebryanyae5b9562016-01-15 06:24:05 +000033static bool RecordingMemcmp = false;
Kostya Serebryanyc135b552016-07-15 23:27:19 +000034static bool RecordingMemmem = false;
Kostya Serebryany6b08be92016-07-19 18:29:06 +000035static bool DoingMyOwnMemmem = false;
36
37struct ScopedDoingMyOwnMemmem {
38 ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = true; }
39 ~ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = false; }
40};
Kostya Serebryanyae5b9562016-01-15 06:24:05 +000041
Kostya Serebryany22526252015-05-11 21:16:27 +000042class TraceState {
Mike Aizatskyf0b3e852016-06-23 20:44:48 +000043public:
44 TraceState(MutationDispatcher &MD, const FuzzingOptions &Options,
Richard Smithb62e7e32016-05-27 21:05:35 +000045 const Fuzzer *F)
Kostya Serebryanyf26017b2016-05-26 21:32:30 +000046 : MD(MD), Options(Options), F(F) {}
Kostya Serebryany16d03bd2015-03-30 22:09:51 +000047
Kostya Serebryanyc5733162016-01-09 01:39:55 +000048 void TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1,
49 const uint8_t *Data2);
Kostya Serebryanyfb7d8d92015-07-31 01:33:06 +000050
51 void TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, uint64_t Val,
52 size_t NumCases, uint64_t *Cases);
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +000053 int TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
Kostya Serebryanyf26017b2016-05-26 21:32:30 +000054 size_t DataSize);
Kostya Serebryanyc5733162016-01-09 01:39:55 +000055 int TryToAddDesiredData(const uint8_t *PresentData,
56 const uint8_t *DesiredData, size_t DataSize);
Kostya Serebryanybeb24c32015-05-07 21:02:11 +000057
58 void StartTraceRecording() {
Kostya Serebryany5c04bd22016-09-09 01:17:03 +000059 if (!Options.UseMemcmp)
Kostya Serebryanyf26017b2016-05-26 21:32:30 +000060 return;
Kostya Serebryanyae5b9562016-01-15 06:24:05 +000061 RecordingMemcmp = Options.UseMemcmp;
Kostya Serebryanyc135b552016-07-15 23:27:19 +000062 RecordingMemmem = Options.UseMemmem;
Kostya Serebryanye7583d22016-01-09 00:38:40 +000063 NumMutations = 0;
Kostya Serebryanyc135b552016-07-15 23:27:19 +000064 InterestingWords.clear();
Kostya Serebryany7ec0c562016-02-13 03:25:16 +000065 MD.ClearAutoDictionary();
Kostya Serebryanybeb24c32015-05-07 21:02:11 +000066 }
67
Kostya Serebryanyb65805a2016-01-09 03:08:58 +000068 void StopTraceRecording() {
Kostya Serebryany5c04bd22016-09-09 01:17:03 +000069 if (!RecordingMemcmp)
Mike Aizatskyf0b3e852016-06-23 20:44:48 +000070 return;
Kostya Serebryanyae5b9562016-01-15 06:24:05 +000071 RecordingMemcmp = false;
Kostya Serebryanyb65805a2016-01-09 03:08:58 +000072 for (size_t i = 0; i < NumMutations; i++) {
73 auto &M = Mutations[i];
Kostya Serebryany859e86d2016-01-12 02:08:37 +000074 if (Options.Verbosity >= 2) {
Kostya Serebryany476f0ce2016-01-16 03:53:32 +000075 AutoDictUnitCounts[M.W]++;
Kostya Serebryany859e86d2016-01-12 02:08:37 +000076 AutoDictAdds++;
77 if ((AutoDictAdds & (AutoDictAdds - 1)) == 0) {
Kostya Serebryany476f0ce2016-01-16 03:53:32 +000078 typedef std::pair<size_t, Word> CU;
Kostya Serebryany859e86d2016-01-12 02:08:37 +000079 std::vector<CU> CountedUnits;
80 for (auto &I : AutoDictUnitCounts)
81 CountedUnits.push_back(std::make_pair(I.second, I.first));
82 std::sort(CountedUnits.begin(), CountedUnits.end(),
83 [](const CU &a, const CU &b) { return a.first > b.first; });
84 Printf("AutoDict:\n");
85 for (auto &I : CountedUnits) {
86 Printf(" %zd ", I.first);
Kostya Serebryany6f5a8042016-09-21 01:50:50 +000087 PrintASCII(I.second.data(), I.second.size());
Kostya Serebryany859e86d2016-01-12 02:08:37 +000088 Printf("\n");
89 }
90 }
91 }
Kostya Serebryanyc135b552016-07-15 23:27:19 +000092 MD.AddWordToAutoDictionary({M.W, M.Pos});
Kostya Serebryanyb65805a2016-01-09 03:08:58 +000093 }
Kostya Serebryanyc135b552016-07-15 23:27:19 +000094 for (auto &W : InterestingWords)
95 MD.AddWordToAutoDictionary({W});
Kostya Serebryanybeb24c32015-05-07 21:02:11 +000096 }
97
Kostya Serebryanyc5733162016-01-09 01:39:55 +000098 void AddMutation(uint32_t Pos, uint32_t Size, const uint8_t *Data) {
Kostya Serebryanye7583d22016-01-09 00:38:40 +000099 if (NumMutations >= kMaxMutations) return;
100 auto &M = Mutations[NumMutations++];
101 M.Pos = Pos;
Kostya Serebryany476f0ce2016-01-16 03:53:32 +0000102 M.W.Set(Data, Size);
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000103 }
104
105 void AddMutation(uint32_t Pos, uint32_t Size, uint64_t Data) {
106 assert(Size <= sizeof(Data));
107 AddMutation(Pos, Size, reinterpret_cast<uint8_t*>(&Data));
Kostya Serebryanye7583d22016-01-09 00:38:40 +0000108 }
109
Kostya Serebryanyc135b552016-07-15 23:27:19 +0000110 void AddInterestingWord(const uint8_t *Data, size_t Size) {
111 if (!RecordingMemmem || !F->InFuzzingThread()) return;
112 if (Size <= 1) return;
113 Size = std::min(Size, Word::GetMaxSize());
114 Word W(Data, Size);
115 InterestingWords.insert(W);
116 }
117
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000118 private:
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000119 bool IsTwoByteData(uint64_t Data) {
120 int64_t Signed = static_cast<int64_t>(Data);
121 Signed >>= 16;
122 return Signed == 0 || Signed == -1L;
123 }
Kostya Serebryanyd88d1302016-02-02 23:17:45 +0000124
125 // We don't want to create too many trace-based mutations as it is both
126 // expensive and useless. So after some number of mutations is collected,
127 // start rejecting some of them. The more there are mutations the more we
128 // reject.
129 bool WantToHandleOneMoreMutation() {
130 const size_t FirstN = 64;
131 // Gladly handle first N mutations.
132 if (NumMutations <= FirstN) return true;
133 size_t Diff = NumMutations - FirstN;
134 size_t DiffLog = sizeof(long) * 8 - __builtin_clzl((long)Diff);
135 assert(DiffLog > 0 && DiffLog < 64);
Kostya Serebryany7ec0c562016-02-13 03:25:16 +0000136 bool WantThisOne = MD.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog.
Kostya Serebryanyd88d1302016-02-02 23:17:45 +0000137 return WantThisOne;
138 }
139
Kostya Serebryanye7583d22016-01-09 00:38:40 +0000140 static const size_t kMaxMutations = 1 << 16;
141 size_t NumMutations;
142 TraceBasedMutation Mutations[kMaxMutations];
Kostya Serebryanyc135b552016-07-15 23:27:19 +0000143 // TODO: std::set is too inefficient, need to have a custom DS here.
144 std::set<Word> InterestingWords;
Kostya Serebryany7ec0c562016-02-13 03:25:16 +0000145 MutationDispatcher &MD;
Mike Aizatskyf0b3e852016-06-23 20:44:48 +0000146 const FuzzingOptions Options;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000147 const Fuzzer *F;
Kostya Serebryany476f0ce2016-01-16 03:53:32 +0000148 std::map<Word, size_t> AutoDictUnitCounts;
Kostya Serebryany859e86d2016-01-12 02:08:37 +0000149 size_t AutoDictAdds = 0;
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000150};
151
Kostya Serebryany22526252015-05-11 21:16:27 +0000152int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000153 size_t DataSize) {
Kostya Serebryanyd88d1302016-02-02 23:17:45 +0000154 if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0;
Kostya Serebryany6b08be92016-07-19 18:29:06 +0000155 ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000156 const uint8_t *UnitData;
157 auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData);
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000158 int Res = 0;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000159 const uint8_t *Beg = UnitData;
160 const uint8_t *End = Beg + UnitSize;
Kostya Serebryanye641dd62015-09-04 22:32:25 +0000161 for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000162 Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize);
163 if (!Cur)
164 break;
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000165 size_t Pos = Cur - Beg;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000166 assert(Pos < UnitSize);
Kostya Serebryanye7583d22016-01-09 00:38:40 +0000167 AddMutation(Pos, DataSize, DesiredData);
168 AddMutation(Pos, DataSize, DesiredData + 1);
169 AddMutation(Pos, DataSize, DesiredData - 1);
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000170 Res++;
171 }
172 return Res;
173}
174
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000175int TraceState::TryToAddDesiredData(const uint8_t *PresentData,
176 const uint8_t *DesiredData,
177 size_t DataSize) {
Kostya Serebryanyd88d1302016-02-02 23:17:45 +0000178 if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0;
Kostya Serebryany6b08be92016-07-19 18:29:06 +0000179 ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000180 const uint8_t *UnitData;
181 auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData);
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000182 int Res = 0;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000183 const uint8_t *Beg = UnitData;
184 const uint8_t *End = Beg + UnitSize;
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000185 for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
186 Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize);
187 if (!Cur)
188 break;
189 size_t Pos = Cur - Beg;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000190 assert(Pos < UnitSize);
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000191 AddMutation(Pos, DataSize, DesiredData);
192 Res++;
193 }
194 return Res;
195}
196
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000197void TraceState::TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1,
198 const uint8_t *Data2) {
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000199 if (!RecordingMemcmp || !F->InFuzzingThread()) return;
Kostya Serebryany476f0ce2016-01-16 03:53:32 +0000200 CmpSize = std::min(CmpSize, Word::GetMaxSize());
Kostya Serebryany1f9c40d2016-01-09 03:46:08 +0000201 int Added2 = TryToAddDesiredData(Data1, Data2, CmpSize);
202 int Added1 = TryToAddDesiredData(Data2, Data1, CmpSize);
203 if ((Added1 || Added2) && Options.Verbosity >= 3) {
204 Printf("MemCmp Added %d%d: ", Added1, Added2);
Kostya Serebryany41740052016-01-12 02:36:59 +0000205 if (Added1) PrintASCII(Data1, CmpSize);
206 if (Added2) PrintASCII(Data2, CmpSize);
Kostya Serebryany1f9c40d2016-01-09 03:46:08 +0000207 Printf("\n");
208 }
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000209}
210
Kostya Serebryanyfb7d8d92015-07-31 01:33:06 +0000211void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits,
212 uint64_t Val, size_t NumCases,
213 uint64_t *Cases) {
Kostya Serebryany5c04bd22016-09-09 01:17:03 +0000214 if (F->InFuzzingThread()) return;
Kostya Serebryanyfe7e41e2015-07-31 20:58:55 +0000215 size_t ValSize = ValSizeInBits / 8;
216 bool TryShort = IsTwoByteData(Val);
Kostya Serebryanyfb7d8d92015-07-31 01:33:06 +0000217 for (size_t i = 0; i < NumCases; i++)
Kostya Serebryanyfe7e41e2015-07-31 20:58:55 +0000218 TryShort &= IsTwoByteData(Cases[i]);
219
220 if (Options.Verbosity >= 3)
221 Printf("TraceSwitch: %p %zd # %zd; TryShort %d\n", PC, Val, NumCases,
222 TryShort);
223
224 for (size_t i = 0; i < NumCases; i++) {
225 TryToAddDesiredData(Val, Cases[i], ValSize);
226 if (TryShort)
227 TryToAddDesiredData(Val, Cases[i], 2);
228 }
Kostya Serebryanyfb7d8d92015-07-31 01:33:06 +0000229}
230
Kostya Serebryany22526252015-05-11 21:16:27 +0000231static TraceState *TS;
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000232
Kostya Serebryanybeb24c32015-05-07 21:02:11 +0000233void Fuzzer::StartTraceRecording() {
Kostya Serebryany22526252015-05-11 21:16:27 +0000234 if (!TS) return;
235 TS->StartTraceRecording();
Kostya Serebryanybeb24c32015-05-07 21:02:11 +0000236}
237
Kostya Serebryanyb65805a2016-01-09 03:08:58 +0000238void Fuzzer::StopTraceRecording() {
239 if (!TS) return;
240 TS->StopTraceRecording();
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000241}
242
Kostya Serebryany22526252015-05-11 21:16:27 +0000243void Fuzzer::InitializeTraceState() {
Kostya Serebryany5c04bd22016-09-09 01:17:03 +0000244 if (!Options.UseMemcmp) return;
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000245 TS = new TraceState(MD, Options, this);
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000246}
247
Kostya Serebryanyc9dc96b2015-07-30 21:22:22 +0000248static size_t InternalStrnlen(const char *S, size_t MaxLen) {
249 size_t Len = 0;
250 for (; Len < MaxLen && S[Len]; Len++) {}
251 return Len;
252}
253
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000254// Value profile.
255// We keep track of various values that affect control flow.
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000256// These values are inserted into a bit-set-based hash map.
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000257// Every new bit in the map is treated as a new coverage.
258//
259// For memcmp/strcmp/etc the interesting value is the length of the common
260// prefix of the parameters.
261// For cmp instructions the interesting value is a XOR of the parameters.
262// The interesting value is mixed up with the PC and is then added to the map.
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000263
264static void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
265 size_t n) {
266 if (!n) return;
267 size_t Len = std::min(n, (size_t)32);
Kostya Serebryanyd4492f82016-08-30 03:05:50 +0000268 const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1);
269 const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2);
270 size_t I = 0;
271 for (; I < Len; I++)
272 if (A1[I] != A2[I])
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000273 break;
274 size_t PC = reinterpret_cast<size_t>(caller_pc);
Kostya Serebryany248d1152016-08-30 14:39:33 +0000275 size_t Idx = I;
276 // if (I < Len)
277 // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000278 TPC.HandleValueProfile((PC & 4095) | (Idx << 12));
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000279}
280
281static void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2,
282 size_t n) {
283 if (!n) return;
284 size_t Len = std::min(n, (size_t)32);
Kostya Serebryanyd4492f82016-08-30 03:05:50 +0000285 const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1);
286 const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2);
287 size_t I = 0;
288 for (; I < Len; I++)
289 if (A1[I] != A2[I] || A1[I] == 0)
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000290 break;
291 size_t PC = reinterpret_cast<size_t>(caller_pc);
Kostya Serebryany248d1152016-08-30 14:39:33 +0000292 size_t Idx = I;
293 // if (I < Len && A1[I])
294 // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000295 TPC.HandleValueProfile((PC & 4095) | (Idx << 12));
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000296}
297
Kostya Serebryanybceadcf2016-08-24 01:38:42 +0000298ATTRIBUTE_TARGET_POPCNT
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000299static void AddValueForCmp(void *PCptr, uint64_t Arg1, uint64_t Arg2) {
Kostya Serebryanyac524cf2016-08-23 23:37:37 +0000300 if (Arg1 == Arg2)
301 return;
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000302 uintptr_t PC = reinterpret_cast<uintptr_t>(PCptr);
Kostya Serebryanyac524cf2016-08-23 23:37:37 +0000303 uint64_t ArgDistance = __builtin_popcountl(Arg1 ^ Arg2) - 1; // [0,63]
304 uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000305 TPC.HandleValueProfile(Idx);
Kostya Serebryanyd46a59f2016-08-16 19:33:51 +0000306}
307
Kostya Serebryany4d22e4f2016-08-30 01:30:14 +0000308static void AddValueForSingleVal(void *PCptr, uintptr_t Val) {
309 if (!Val) return;
310 uintptr_t PC = reinterpret_cast<uintptr_t>(PCptr);
311 uint64_t ArgDistance = __builtin_popcountl(Val) - 1; // [0,63]
312 uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000313 TPC.HandleValueProfile(Idx);
Kostya Serebryany4d22e4f2016-08-30 01:30:14 +0000314}
315
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000316} // namespace fuzzer
317
Kostya Serebryany22526252015-05-11 21:16:27 +0000318using fuzzer::TS;
Kostya Serebryanyae5b9562016-01-15 06:24:05 +0000319using fuzzer::RecordingMemcmp;
Kostya Serebryany5a99ecb2015-05-11 20:51:19 +0000320
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000321extern "C" {
Kostya Serebryany7f4227d2015-08-05 18:23:01 +0000322
Kostya Serebryany4b83a4f2016-01-12 16:50:18 +0000323// We may need to avoid defining weak hooks to stay compatible with older clang.
324#ifndef LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
325# define LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS 1
326#endif
327
328#if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
Kostya Serebryany0e776a22015-07-30 01:34:58 +0000329void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
Kostya Serebryanye3580952016-01-12 00:43:42 +0000330 const void *s2, size_t n, int result) {
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000331 fuzzer::AddValueForMemcmp(caller_pc, s1, s2, n);
Kostya Serebryanyae5b9562016-01-15 06:24:05 +0000332 if (!RecordingMemcmp) return;
Kostya Serebryanye3580952016-01-12 00:43:42 +0000333 if (result == 0) return; // No reason to mutate.
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000334 if (n <= 1) return; // Not interesting.
335 TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1),
336 reinterpret_cast<const uint8_t *>(s2));
Kostya Serebryanyb74ba422015-07-30 02:33:45 +0000337}
338
339void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
Kostya Serebryanye3580952016-01-12 00:43:42 +0000340 const char *s2, size_t n, int result) {
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000341 fuzzer::AddValueForStrcmp(caller_pc, s1, s2, n);
Kostya Serebryanyae5b9562016-01-15 06:24:05 +0000342 if (!RecordingMemcmp) return;
Kostya Serebryanye3580952016-01-12 00:43:42 +0000343 if (result == 0) return; // No reason to mutate.
Kostya Serebryanycd6a4662015-07-31 17:05:05 +0000344 size_t Len1 = fuzzer::InternalStrnlen(s1, n);
345 size_t Len2 = fuzzer::InternalStrnlen(s2, n);
346 n = std::min(n, Len1);
347 n = std::min(n, Len2);
348 if (n <= 1) return; // Not interesting.
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000349 TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1),
350 reinterpret_cast<const uint8_t *>(s2));
Kostya Serebryany0e776a22015-07-30 01:34:58 +0000351}
352
Kostya Serebryany7f4227d2015-08-05 18:23:01 +0000353void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
Kostya Serebryanye3580952016-01-12 00:43:42 +0000354 const char *s2, int result) {
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000355 fuzzer::AddValueForStrcmp(caller_pc, s1, s2, 64);
Kostya Serebryanyae5b9562016-01-15 06:24:05 +0000356 if (!RecordingMemcmp) return;
Kostya Serebryanye3580952016-01-12 00:43:42 +0000357 if (result == 0) return; // No reason to mutate.
Kostya Serebryany7f4227d2015-08-05 18:23:01 +0000358 size_t Len1 = strlen(s1);
359 size_t Len2 = strlen(s2);
360 size_t N = std::min(Len1, Len2);
361 if (N <= 1) return; // Not interesting.
Kostya Serebryanyc5733162016-01-09 01:39:55 +0000362 TS->TraceMemcmpCallback(N, reinterpret_cast<const uint8_t *>(s1),
363 reinterpret_cast<const uint8_t *>(s2));
Kostya Serebryany7f4227d2015-08-05 18:23:01 +0000364}
365
Kostya Serebryanyc135b552016-07-15 23:27:19 +0000366void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
367 const char *s2, size_t n, int result) {
368 return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
369}
370void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
371 const char *s2, int result) {
372 return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
373}
374void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,
375 const char *s2, char *result) {
376 TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
377}
378void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,
379 const char *s2, char *result) {
380 TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
381}
382void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
383 const void *s2, size_t len2, void *result) {
Kostya Serebryany6b08be92016-07-19 18:29:06 +0000384 if (fuzzer::DoingMyOwnMemmem) return;
385 TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2);
Kostya Serebryanyc135b552016-07-15 23:27:19 +0000386}
387
Kostya Serebryany4b83a4f2016-01-12 16:50:18 +0000388#endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
389
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000390// TODO: this one will not be used with the newest clang. Remove it.
Kostya Serebryany3287d7a2015-09-30 22:22:37 +0000391__attribute__((visibility("default")))
Kostya Serebryany7d470cf2015-05-07 18:32:29 +0000392void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
393 uint64_t Arg2) {
Kostya Serebryanyab73c692016-09-23 00:46:18 +0000394 fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000395}
396
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000397__attribute__((visibility("default")))
398void __sanitizer_cov_trace_cmp8(uint64_t Arg1, int64_t Arg2) {
399 fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000400}
401__attribute__((visibility("default")))
402void __sanitizer_cov_trace_cmp4(uint32_t Arg1, int32_t Arg2) {
403 fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000404}
405__attribute__((visibility("default")))
406void __sanitizer_cov_trace_cmp2(uint16_t Arg1, int16_t Arg2) {
407 fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
Kostya Serebryany524c3f32016-08-18 01:25:28 +0000408}
409__attribute__((visibility("default")))
410void __sanitizer_cov_trace_cmp1(uint8_t Arg1, int8_t Arg2) {
411 fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2);
Kostya Serebryany7d470cf2015-05-07 18:32:29 +0000412}
413
Kostya Serebryany3287d7a2015-09-30 22:22:37 +0000414__attribute__((visibility("default")))
Kostya Serebryanyfb7d8d92015-07-31 01:33:06 +0000415void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
Kostya Serebryany5c04bd22016-09-09 01:17:03 +0000416 // TODO(kcc): support value profile here.
Kostya Serebryanyfb7d8d92015-07-31 01:33:06 +0000417}
418
Kostya Serebryany4d22e4f2016-08-30 01:30:14 +0000419__attribute__((visibility("default")))
420void __sanitizer_cov_trace_div4(uint32_t Val) {
421 fuzzer::AddValueForSingleVal(__builtin_return_address(0), Val);
422}
423__attribute__((visibility("default")))
424void __sanitizer_cov_trace_div8(uint64_t Val) {
425 fuzzer::AddValueForSingleVal(__builtin_return_address(0), Val);
426}
427__attribute__((visibility("default")))
428void __sanitizer_cov_trace_gep(uintptr_t Idx) {
429 fuzzer::AddValueForSingleVal(__builtin_return_address(0), Idx);
430}
431
Kostya Serebryany16d03bd2015-03-30 22:09:51 +0000432} // extern "C"