Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 //===- NaClSimpleRecordFuzzer.cpp - Simple fuzzer of bitcode ----*- C++ -*-===// | |
|
jvoung (off chromium)
2015/06/01 17:26:36
No need for -*- C++...
Karl
2015/06/01 22:40:55
Done.
| |
| 2 // | |
| 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 //===----------------------------------------------------------------------===// | |
| 9 // | |
| 10 // This file implements a simple fuzzer for a list of PNaCl bitcode records. | |
|
jvoung (off chromium)
2015/06/01 17:26:36
//===---------------------------------------------
Karl
2015/06/01 22:40:55
Done.
| |
| 11 | |
| 12 #include "llvm/ADT/STLExtras.h" | |
| 13 #include "llvm/Bitcode/NaCl/NaClFuzz.h" | |
| 14 #include "llvm/Support/Format.h" | |
| 15 | |
| 16 #include <array> | |
| 17 #include <cmath> | |
| 18 #include <cstdlib> | |
| 19 #include <map> | |
| 20 #include <set> | |
| 21 | |
| 22 | |
| 23 using namespace llvm; | |
| 24 using namespace naclfuzz; | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 // Counts the number of times each value in a range [0..N) is used (based | |
| 29 // on the number of calls to method increment()). | |
| 30 class DistCounter { | |
| 31 DistCounter(const DistCounter&) = delete; | |
| 32 void operator=(const DistCounter&) = delete; | |
| 33 public: | |
| 34 explicit DistCounter(size_t DistSize) | |
| 35 : Dist(DistSize, 0), Total(0) {} | |
| 36 | |
| 37 // Increments the count for the given value | |
| 38 size_t increment(size_t Value) { | |
| 39 ++Dist[Value]; | |
| 40 ++Total; | |
| 41 return Value; | |
| 42 } | |
| 43 | |
| 44 // Returns the end of the range being checked. | |
| 45 size_t size() const { | |
| 46 return Dist.size(); | |
| 47 } | |
| 48 | |
| 49 // Returns the number of times value was incremented. | |
| 50 size_t operator[](size_t Value) const { | |
| 51 return Dist[Value]; | |
| 52 } | |
| 53 | |
| 54 // Retrns the number of times any value in the distribution was | |
| 55 // incremented. | |
| 56 size_t getTotal() const { | |
| 57 return Total; | |
| 58 } | |
| 59 private: | |
| 60 // The number of times each value was incremented. | |
| 61 std::vector<size_t> Dist; | |
| 62 // The total number of times any value was incremented. | |
| 63 size_t Total; | |
| 64 }; | |
| 65 | |
| 66 // Model weights when randomly choosing values. | |
| 67 typedef unsigned WeightType; | |
| 68 | |
| 69 // Association weights with values. Used to generate weighted | |
|
jvoung (off chromium)
2015/06/01 17:26:36
"Association weights with values" -> Association o
Karl
2015/06/01 22:40:55
Chose "Associates weights with values".
| |
| 70 // distributions (see class WeightedDistribution below). | |
| 71 template<typename T> | |
| 72 struct WeightedValue { | |
| 73 T Value; | |
| 74 WeightType Weight; | |
| 75 }; | |
| 76 | |
| 77 // Weighted distribution for a set of values in [0..DistSize). | |
| 78 template<typename T> | |
| 79 class WeightedDistribution { | |
| 80 WeightedDistribution(const WeightedDistribution&) = delete; | |
| 81 void operator=(const WeightedDistribution&) = delete; | |
| 82 public: | |
| 83 typedef const WeightedValue<T> *const_iterator; | |
| 84 | |
| 85 WeightedDistribution(const WeightedValue<T> Dist[], | |
| 86 size_t DistSize, | |
| 87 RandomNumberGenerator &Generator) | |
| 88 : Dist(Dist), DistSize(DistSize), TotalWeight(0), Generator(Generator) { | |
| 89 for (size_t i = 0; i < DistSize; ++i) | |
| 90 TotalWeight += Dist[i].Weight; | |
| 91 } | |
| 92 | |
| 93 virtual ~WeightedDistribution() {} | |
| 94 | |
| 95 /// Returns the number of weighted values in the distribution. | |
| 96 size_t size() const { | |
| 97 return DistSize; | |
| 98 } | |
| 99 | |
| 100 /// Returns const iterator at beginning of weighted distribution. | |
| 101 const_iterator begin() const { | |
| 102 return Dist; | |
| 103 } | |
| 104 | |
| 105 /// Returns const iterator at end of weighted distribution. | |
| 106 const_iterator end() const { | |
| 107 return Dist + DistSize; | |
| 108 } | |
| 109 | |
| 110 /// Randomly chooses a weighted value in the distribution, based on | |
| 111 /// the weights of the distrubution. | |
| 112 virtual const WeightedValue<T> &choose() { | |
| 113 return Dist[chooseIndex()]; | |
| 114 } | |
| 115 | |
| 116 /// Returns the total weight associated with the distribution. | |
| 117 size_t getTotalWeight() const { | |
| 118 return TotalWeight; | |
| 119 } | |
| 120 | |
| 121 protected: | |
| 122 // The weighted values defining the distribution. | |
| 123 const WeightedValue<T> *Dist; | |
| 124 // The number of weighed values in the distribution. | |
|
jvoung (off chromium)
2015/06/01 17:26:36
The number of weighted values ?
Karl
2015/06/01 22:40:56
Done.
| |
| 125 size_t DistSize; | |
| 126 // The total weight of the distribution (sum of weights in weighted values). | |
| 127 size_t TotalWeight; | |
| 128 // The random number generator to use. | |
| 129 RandomNumberGenerator &Generator; | |
| 130 | |
| 131 // Randomly chooses an index of a weighed value in the distribution, | |
| 132 // based on the weights of the distribution. | |
| 133 // chosen element. | |
|
jvoung (off chromium)
2015/06/01 17:26:35
"""
// ... of the distribution.
// chosen element.
Karl
2015/06/01 22:40:55
Removed last sentence.
| |
| 134 size_t chooseIndex() { | |
| 135 /// TODO(kschimpf) Speed this up? | |
| 136 WeightType WeightedSum = Generator.chooseInRange(TotalWeight); | |
| 137 assert(WeightedSum < TotalWeight); | |
| 138 for (size_t Choice = 0; Choice < DistSize; ++Choice) { | |
| 139 WeightType NextWeight = Dist[Choice].Weight; | |
| 140 if (WeightedSum < NextWeight) | |
| 141 return Choice; | |
| 142 WeightedSum -= NextWeight; | |
| 143 } | |
| 144 llvm_unreachable("no index for WeightedDistribution.chooseIndex()"); | |
| 145 } | |
| 146 }; | |
| 147 | |
| 148 // Defines a range [min..limit). | |
| 149 template<typename T> | |
| 150 struct RangeType { | |
| 151 T min; | |
| 152 T limit; | |
| 153 }; | |
| 154 | |
| 155 // Weighted distribution of a set of value ranges. | |
| 156 template<typename T> | |
| 157 class WeightedRangeDistribution : public WeightedDistribution<RangeType<T>> { | |
| 158 WeightedRangeDistribution(const WeightedRangeDistribution<T>&) = delete; | |
| 159 void operator=(const WeightedRangeDistribution<T>&) = delete; | |
| 160 public: | |
| 161 WeightedRangeDistribution(const WeightedValue<RangeType<T>> Dist[], | |
| 162 size_t DistSize, | |
| 163 RandomNumberGenerator &Generator) | |
| 164 : WeightedDistribution<RangeType<T>>(Dist, DistSize, Generator) {} | |
| 165 | |
| 166 // Choose a value from one of the value ranges. | |
| 167 T chooseValue() { | |
| 168 const RangeType<T> Range = this->choose().Value; | |
| 169 return Range.min + | |
| 170 this->Generator.chooseInRange(Range.limit - Range.min + 1); | |
|
jvoung (off chromium)
2015/06/01 17:26:36
Just checking -- Should this really have + 1?
The
Karl
2015/06/01 22:40:55
Hmm. I guess I meant a range is [min..max] rather
| |
| 171 } | |
| 172 }; | |
| 173 | |
| 174 /// Weighted distribution with a counter, capturing the distribution | |
| 175 /// of random choices for each weighted value. | |
| 176 template<typename T> | |
| 177 class CountedWeightedDistribution : public WeightedDistribution<T> { | |
| 178 CountedWeightedDistribution(const CountedWeightedDistribution&) = delete; | |
| 179 void operator=(const CountedWeightedDistribution&) = delete; | |
| 180 public: | |
| 181 CountedWeightedDistribution(const WeightedValue<T> Dist[], | |
| 182 size_t DistSize, | |
| 183 RandomNumberGenerator &Generator) | |
| 184 : WeightedDistribution<T>(Dist, DistSize, Generator), Counter(DistSize) {} | |
| 185 | |
| 186 const WeightedValue<T> &choose() final { | |
| 187 return this->Dist[Counter.increment( | |
| 188 WeightedDistribution<T>::chooseIndex())]; | |
| 189 } | |
| 190 | |
| 191 /// Returns the number of times the Index-th weighted value was | |
| 192 /// chosen. | |
| 193 size_t getChooseCount(size_t Index) const { | |
| 194 return Counter[Index]; | |
| 195 } | |
| 196 | |
| 197 /// Returns the total number of times method choose was called. | |
| 198 size_t getTotalChooseCount() const { | |
| 199 return Counter.getTotal(); | |
| 200 } | |
| 201 | |
| 202 private: | |
| 203 DistCounter Counter; | |
| 204 }; | |
| 205 | |
| 206 #define ARRAY(array) array, array_lengthof(array) | |
| 207 | |
| 208 // Weighted distribution used to select edit actions. | |
| 209 const WeightedValue<RecordFuzzer::EditAction> ActionDist[] = { | |
| 210 {RecordFuzzer::InsertRecord, 3}, | |
| 211 {RecordFuzzer::MutateRecord, 5}, | |
| 212 {RecordFuzzer::RemoveRecord, 1}, | |
| 213 {RecordFuzzer::ReplaceRecord, 1}, | |
| 214 {RecordFuzzer::SwapRecord, 1} | |
| 215 }; | |
| 216 | |
| 217 // Type of values in bitcode records. | |
| 218 typedef uint64_t ValueType; | |
| 219 // Signed version of values. | |
| 220 typedef int64_t SignedValueType; | |
| 221 | |
| 222 // Weighted ranges for nonegative values in records. | |
|
jvoung (off chromium)
2015/06/01 17:26:36
nonegative -> non-negative
Karl
2015/06/01 22:40:55
Done.
| |
| 223 const WeightedValue<RangeType<ValueType>> PosValueDist[] = { | |
| 224 {{0, 6}, 100}, | |
| 225 {{7, 20}, 50}, | |
| 226 {{21, 40}, 10}, | |
| 227 {{41, 100}, 2}, | |
| 228 {{101, 4096}, 1} | |
| 229 }; | |
| 230 | |
| 231 // Distribution used to decide when use negative values in records. | |
| 232 WeightedValue<bool> NegValueDist[] = { | |
| 233 {true, 1}, // i.e. make value negative. | |
| 234 {false, 100} // i.e. leave value positive. | |
| 235 }; | |
| 236 | |
| 237 // Range distribution for records sizes (must be greater than 0). | |
| 238 const WeightedValue<RangeType<size_t>> RecordSizeDist[] = { | |
| 239 {{1, 3}, 1000}, | |
| 240 {{4, 7}, 100}, | |
| 241 {{7, 100}, 1} | |
| 242 }; | |
| 243 | |
| 244 // Defines valid record codes. | |
| 245 typedef unsigned RecordCodeType; | |
| 246 | |
| 247 // Special code to signify adding random other record codes. | |
| 248 static const RecordCodeType OtherRecordCode = 575757575; | |
| 249 | |
| 250 // List of record codes we can generate. The weights are based | |
| 251 // on record counts in pnacl-llc.pexe, using how many thousand of | |
| 252 // each record code appeared (or 1 if less than 1 thousand). | |
|
jvoung (off chromium)
2015/06/01 17:26:35
There is some overlap in the way the codes are num
Karl
2015/06/01 22:40:55
I agree that there are overlapping entries, since
| |
| 253 WeightedValue<RecordCodeType> RecordCodeDist[] = { | |
| 254 {naclbitc::BLOCKINFO_CODE_SETBID, 1}, | |
| 255 {naclbitc::MODULE_CODE_VERSION, 1}, | |
| 256 {naclbitc::MODULE_CODE_FUNCTION, 7}, | |
| 257 {naclbitc::TYPE_CODE_NUMENTRY, 1}, | |
| 258 {naclbitc::TYPE_CODE_VOID, 1}, | |
| 259 {naclbitc::TYPE_CODE_FLOAT, 1}, | |
| 260 {naclbitc::TYPE_CODE_DOUBLE, 1}, | |
| 261 {naclbitc::TYPE_CODE_INTEGER, 1}, | |
| 262 {naclbitc::TYPE_CODE_VECTOR, 1}, | |
| 263 {naclbitc::TYPE_CODE_FUNCTION, 1}, | |
| 264 {naclbitc::VST_CODE_ENTRY, 1}, | |
| 265 {naclbitc::VST_CODE_BBENTRY, 1}, | |
| 266 {naclbitc::CST_CODE_SETTYPE, 15}, | |
| 267 {naclbitc::CST_CODE_UNDEF, 1}, | |
| 268 {naclbitc::CST_CODE_INTEGER, 115}, | |
| 269 {naclbitc::CST_CODE_FLOAT, 1}, | |
| 270 {naclbitc::GLOBALVAR_VAR, 14}, | |
| 271 {naclbitc::GLOBALVAR_COMPOUND, 1}, | |
| 272 {naclbitc::GLOBALVAR_ZEROFILL, 2}, | |
| 273 {naclbitc::GLOBALVAR_DATA, 18}, | |
| 274 {naclbitc::GLOBALVAR_RELOC, 20}, | |
| 275 {naclbitc::GLOBALVAR_COUNT, 1}, | |
| 276 {naclbitc::FUNC_CODE_DECLAREBLOCKS, 6}, | |
| 277 {naclbitc::FUNC_CODE_INST_BINOP, 402}, | |
| 278 {naclbitc::FUNC_CODE_INST_CAST, 61}, | |
| 279 {naclbitc::FUNC_CODE_INST_EXTRACTELT, 1}, | |
| 280 {naclbitc::FUNC_CODE_INST_INSERTELT, 1}, | |
| 281 {naclbitc::FUNC_CODE_INST_RET, 7}, | |
| 282 {naclbitc::FUNC_CODE_INST_BR, 223}, | |
| 283 {naclbitc::FUNC_CODE_INST_SWITCH, 7}, | |
| 284 {naclbitc::FUNC_CODE_INST_UNREACHABLE, 1}, | |
| 285 {naclbitc::FUNC_CODE_INST_PHI, 84}, | |
| 286 {naclbitc::FUNC_CODE_INST_ALLOCA, 34}, | |
| 287 {naclbitc::FUNC_CODE_INST_LOAD, 225}, | |
| 288 {naclbitc::FUNC_CODE_INST_STORE, 461}, | |
| 289 {naclbitc::FUNC_CODE_INST_CMP2, 140}, | |
| 290 {naclbitc::FUNC_CODE_INST_VSELECT, 10}, | |
| 291 {naclbitc::FUNC_CODE_INST_CALL, 80}, | |
| 292 {naclbitc::FUNC_CODE_INST_FORWARDTYPEREF, 36}, | |
| 293 {naclbitc::FUNC_CODE_INST_CALL_INDIRECT, 5}, | |
| 294 {naclbitc::BLK_CODE_ENTER, 1}, | |
| 295 {naclbitc::BLK_CODE_EXIT, 1}, | |
| 296 {naclbitc::BLK_CODE_DEFINE_ABBREV, 1}, | |
| 297 {OtherRecordCode, 1} | |
| 298 }; | |
| 299 | |
| 300 // *Warning* The current implementation does not work on empty bitcode | |
| 301 // record lists. | |
| 302 class SimpleRecordFuzzer : public RecordFuzzer { | |
| 303 public: | |
| 304 explicit SimpleRecordFuzzer(NaClMungedBitcode &Bitcode, | |
|
jvoung (off chromium)
2015/06/01 17:26:36
no need for explicit
Karl
2015/06/01 22:40:55
Done.
| |
| 305 RandomNumberGenerator &Generator) | |
| 306 : RecordFuzzer(Bitcode, Generator), | |
| 307 RecordCounter(Bitcode.getBaseRecords().size()), | |
| 308 ActionWeight(ARRAY(ActionDist), Generator), | |
| 309 RecordSizeWeight(ARRAY(RecordSizeDist), Generator), | |
| 310 PosValueWeight(ARRAY(PosValueDist), Generator), | |
| 311 NegValueWeight(ARRAY(NegValueDist), Generator), | |
| 312 RecordCodeWeight(ARRAY(RecordCodeDist), Generator) { | |
| 313 | |
| 314 assert(!Bitcode.getBaseRecords().empty() | |
| 315 && "Can't fuzz empty list of records"); | |
| 316 | |
| 317 for (const auto RecordCode : RecordCodeWeight) | |
|
jvoung (off chromium)
2015/06/01 17:26:36
"auto &" or ? Can't tell if it's already a referen
Karl
2015/06/01 22:40:55
Done.
| |
| 318 UsedRecordCodes.insert(RecordCode.Value); | |
| 319 | |
|
jvoung (off chromium)
2015/06/01 17:26:36
extra blank line
Karl
2015/06/01 22:40:55
Done.
| |
| 320 } | |
| 321 | |
| 322 ~SimpleRecordFuzzer() final; | |
| 323 | |
| 324 bool fuzz(unsigned Count, unsigned Base) final; | |
| 325 | |
| 326 void showRecordDistribution(raw_ostream &Out) const final; | |
| 327 | |
| 328 void showEditDistribution(raw_ostream &Out) const final; | |
| 329 | |
| 330 private: | |
| 331 // Count how many edits are applied to each record in the bitcode. | |
| 332 DistCounter RecordCounter; | |
| 333 // Distribution used to randomly choose edit actions. | |
| 334 CountedWeightedDistribution<RecordFuzzer::EditAction> ActionWeight; | |
| 335 // Distribution used to randomly choose the size of created records. | |
| 336 WeightedRangeDistribution<size_t> RecordSizeWeight; | |
| 337 // Distribution used to randomly choose positive values for records. | |
| 338 WeightedRangeDistribution<ValueType> PosValueWeight; | |
| 339 // Distribution of value sign used to randomly choose value for records. | |
| 340 WeightedDistribution<bool> NegValueWeight; | |
| 341 // Distribution used to choose record codes for records. | |
| 342 WeightedDistribution<RecordCodeType> RecordCodeWeight; | |
| 343 // Filter to make sure the "other" choice for record codes will not | |
| 344 // choose any other record code in RecordCodeWeight. | |
| 345 std::set<size_t> UsedRecordCodes; | |
| 346 | |
| 347 // Randomly choose an edit action. | |
| 348 RecordFuzzer::EditAction chooseAction() { | |
| 349 return ActionWeight.choose().Value; | |
| 350 } | |
| 351 | |
| 352 // Randomly choose a record index from the list of records to edit. | |
| 353 size_t chooseRecordIndex() { | |
| 354 return RecordCounter.increment( | |
| 355 Generator.chooseInRange(Bitcode.getBaseRecords().size())); | |
| 356 } | |
| 357 | |
| 358 // Randomly choose a record code. | |
| 359 RecordCodeType chooseRecordCode() { | |
| 360 RecordCodeType Code = RecordCodeWeight.choose().Value; | |
| 361 if (Code != OtherRecordCode) | |
| 362 return Code; | |
| 363 Code = Generator.chooseInRange(UINT_MAX); | |
| 364 while (UsedRecordCodes.count(Code)) // don't use predefined values. | |
| 365 ++Code; | |
| 366 return Code; | |
| 367 } | |
| 368 | |
| 369 // Randomly choose a positive value for use in a record. | |
| 370 ValueType choosePositiveValue() { | |
| 371 return PosValueWeight.chooseValue(); | |
| 372 } | |
| 373 | |
| 374 // Randomly choose a positive/negative value for use in a record. | |
| 375 ValueType chooseValue() { | |
| 376 ValueType Value = choosePositiveValue(); | |
| 377 if (NegValueWeight.choose().Value) { | |
| 378 SignedValueType SignedValue = static_cast<SignedValueType>(Value); | |
|
jvoung (off chromium)
2015/06/01 17:26:35
I think technically, if Value > INT_MAX then casti
Karl
2015/06/01 22:40:55
Choosing to use two's complement negation.
| |
| 379 SignedValue = -SignedValue; | |
| 380 Value = static_cast<ValueType>(SignedValue); | |
| 381 } | |
| 382 return Value; | |
| 383 } | |
| 384 | |
| 385 // Randomly fill in a record with record values. | |
| 386 void chooseRecordValues(NaClBitcodeAbbrevRecord &Record) { | |
| 387 Record.Abbrev = naclbitc::UNABBREV_RECORD; | |
| 388 Record.Code = chooseRecordCode(); | |
| 389 Record.Values.clear(); | |
| 390 size_t NumValues = RecordSizeWeight.chooseValue(); | |
| 391 for (size_t i = 0; i < NumValues; ++i) { | |
| 392 Record.Values.push_back(chooseValue()); | |
| 393 } | |
| 394 } | |
| 395 | |
| 396 // Apply the given edit action to a random record. | |
| 397 void applyAction(EditAction Action); | |
| 398 | |
| 399 // Randomly mutate a record. | |
| 400 void mutateRecord(NaClBitcodeAbbrevRecord &Record) { | |
| 401 // TODO: Do something smarter than just changing a value | |
|
jvoung (off chromium)
2015/06/01 17:26:35
TODO(kschimpf) ?
Karl
2015/06/01 22:40:55
Done.
| |
| 402 // in the record. | |
| 403 size_t Index = Generator.chooseInRange(Record.Values.size() + 1); | |
| 404 if (Index == 0) | |
| 405 Record.Code = chooseRecordCode(); | |
| 406 else | |
| 407 Record.Values[Index - 1] = chooseValue(); | |
| 408 } | |
| 409 }; | |
| 410 | |
| 411 SimpleRecordFuzzer::~SimpleRecordFuzzer() {} | |
| 412 | |
| 413 bool SimpleRecordFuzzer::fuzz(unsigned Count, unsigned Base) { | |
| 414 // TODO(kschimpf): Add some randomness in the number of actions selected. | |
| 415 clear(); | |
| 416 size_t NumRecords = Bitcode.getBaseRecords().size(); | |
| 417 size_t NumActions = NumRecords * Count / Base; | |
| 418 if (NumActions == 0) | |
| 419 NumActions = 1; | |
| 420 for (size_t i = 0; i < NumActions; ++i) | |
| 421 applyAction(chooseAction()); | |
| 422 return true; | |
| 423 } | |
| 424 | |
| 425 void SimpleRecordFuzzer::applyAction(EditAction Action) { | |
| 426 size_t Index = chooseRecordIndex(); | |
| 427 switch(Action) { | |
| 428 case InsertRecord: { | |
| 429 NaClBitcodeAbbrevRecord Record; | |
| 430 chooseRecordValues(Record); | |
| 431 if (Generator.chooseInRange(2)) | |
| 432 Bitcode.addBefore(Index, Record); | |
| 433 else | |
| 434 Bitcode.addAfter(Index, Record); | |
| 435 return; | |
| 436 } | |
| 437 case RemoveRecord: | |
| 438 Bitcode.remove(Index); | |
| 439 return; | |
| 440 case ReplaceRecord: { | |
| 441 NaClBitcodeAbbrevRecord Record; | |
| 442 chooseRecordValues(Record); | |
| 443 Bitcode.replace(Index, Record); | |
| 444 return; | |
| 445 } | |
| 446 case MutateRecord: { | |
| 447 NaClBitcodeAbbrevRecord Copy(*Bitcode.getBaseRecords()[Index]); | |
| 448 mutateRecord(Copy); | |
| 449 Bitcode.replace(Index, Copy); | |
| 450 return; | |
| 451 } | |
| 452 case SwapRecord: { | |
| 453 size_t Index2 = chooseRecordIndex(); | |
| 454 Bitcode.replace(Index, *Bitcode.getBaseRecords()[Index2]); | |
| 455 Bitcode.replace(Index2, *Bitcode.getBaseRecords()[Index]); | |
| 456 return; | |
| 457 } | |
| 458 } | |
| 459 } | |
| 460 | |
| 461 // Returns corresponding percenage defined by Count/Total, in a form | |
|
jvoung (off chromium)
2015/06/01 17:26:35
percenage -> percentage
Karl
2015/06/01 22:40:56
Done.
| |
| 462 // that can be printed to a raw_ostream. | |
| 463 format_object<float> percentage(size_t Count, size_t Total) { | |
| 464 float percent = Total == 0.0 ? 0.0 : 100.0 * Count / Total; | |
| 465 return format("%1.0f", nearbyintf(percent)); | |
| 466 } | |
| 467 | |
| 468 void SimpleRecordFuzzer::showRecordDistribution(raw_ostream &Out) const { | |
| 469 Out << "Edit Record Distribution (Total: " << RecordCounter.getTotal() | |
| 470 << "):\n"; | |
| 471 size_t Total = RecordCounter.getTotal(); | |
| 472 for (size_t i = 0; i < Bitcode.getBaseRecords().size(); ++i) { | |
| 473 size_t Count = RecordCounter[i]; | |
| 474 Out << " " << format("%zd", i) << ": " | |
| 475 << Count << " (" << percentage(Count, Total) << "%)\n"; | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 void SimpleRecordFuzzer::showEditDistribution(raw_ostream &Out) const { | |
| 480 size_t TotalWeight = ActionWeight.getTotalWeight(); | |
| 481 size_t TotalCount = ActionWeight.getTotalChooseCount(); | |
| 482 Out << "Edit Action Distribution(Total: " << TotalCount << "):\n"; | |
| 483 size_t ActionIndex = 0; | |
| 484 for (const auto &Action : ActionWeight) { | |
| 485 size_t ActionCount = ActionWeight.getChooseCount(ActionIndex); | |
| 486 Out << " " << actionName(Action.Value) << " - Wanted: " | |
| 487 << percentage(Action.Weight, TotalWeight) << "%, Applied: " | |
| 488 << ActionCount << " (" << percentage(ActionCount, TotalCount) | |
| 489 << "%)\n"; | |
| 490 ++ActionIndex; | |
| 491 } | |
| 492 } | |
| 493 | |
| 494 } // end of anonymous | |
|
jvoung (off chromium)
2015/06/01 17:26:36
"end of anonymous namespace" ? Don't remember the
Karl
2015/06/01 22:40:55
Done.
| |
| 495 | |
| 496 namespace naclfuzz { | |
| 497 | |
| 498 RecordFuzzer *RecordFuzzer::createSimpleRecordFuzzer( | |
| 499 NaClMungedBitcode &Bitcode, | |
| 500 RandomNumberGenerator &Generator) { | |
| 501 return new SimpleRecordFuzzer(Bitcode, Generator); | |
| 502 } | |
| 503 | |
| 504 } // end of namespace naclfuzz | |
| OLD | NEW |