2017-08-21 23:25:50 +00:00
|
|
|
//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===//
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-08-21 23:25:50 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Util functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_FUZZER_UTIL_H
|
|
|
|
#define LLVM_FUZZER_UTIL_H
|
|
|
|
|
2019-01-09 21:46:09 +00:00
|
|
|
#include "FuzzerBuiltins.h"
|
|
|
|
#include "FuzzerBuiltinsMsvc.h"
|
2017-12-04 19:25:59 +00:00
|
|
|
#include "FuzzerCommand.h"
|
2019-01-09 21:46:09 +00:00
|
|
|
#include "FuzzerDefs.h"
|
2017-08-21 23:25:50 +00:00
|
|
|
|
|
|
|
namespace fuzzer {
|
|
|
|
|
|
|
|
void PrintHexArray(const Unit &U, const char *PrintAfter = "");
|
|
|
|
|
|
|
|
void PrintHexArray(const uint8_t *Data, size_t Size,
|
|
|
|
const char *PrintAfter = "");
|
|
|
|
|
|
|
|
void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
|
|
|
|
|
|
|
|
void PrintASCII(const Unit &U, const char *PrintAfter = "");
|
|
|
|
|
|
|
|
// Changes U to contain only ASCII (isprint+isspace) characters.
|
|
|
|
// Returns true iff U has been changed.
|
|
|
|
bool ToASCII(uint8_t *Data, size_t Size);
|
|
|
|
|
|
|
|
bool IsASCII(const Unit &U);
|
|
|
|
|
|
|
|
bool IsASCII(const uint8_t *Data, size_t Size);
|
|
|
|
|
|
|
|
std::string Base64(const Unit &U);
|
|
|
|
|
|
|
|
void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC);
|
|
|
|
|
|
|
|
std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC);
|
|
|
|
|
2018-05-08 23:45:05 +00:00
|
|
|
void PrintStackTrace();
|
|
|
|
|
|
|
|
void PrintMemoryProfile();
|
|
|
|
|
2017-08-21 23:25:50 +00:00
|
|
|
unsigned NumberOfCpuCores();
|
|
|
|
|
|
|
|
// Platform specific functions.
|
|
|
|
void SetSignalHandler(const FuzzingOptions& Options);
|
|
|
|
|
|
|
|
void SleepSeconds(int Seconds);
|
|
|
|
|
|
|
|
unsigned long GetPid();
|
|
|
|
|
|
|
|
size_t GetPeakRSSMb();
|
|
|
|
|
2017-12-04 19:25:59 +00:00
|
|
|
int ExecuteCommand(const Command &Cmd);
|
2020-02-12 15:43:44 -08:00
|
|
|
bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput);
|
2017-08-21 23:25:50 +00:00
|
|
|
|
2020-02-12 15:43:44 -08:00
|
|
|
// Fuchsia does not have popen/pclose.
|
2017-08-21 23:25:50 +00:00
|
|
|
FILE *OpenProcessPipe(const char *Command, const char *Mode);
|
2020-02-10 14:31:47 -08:00
|
|
|
int CloseProcessPipe(FILE *F);
|
2017-08-21 23:25:50 +00:00
|
|
|
|
2021-05-26 15:14:37 -07:00
|
|
|
const void *SearchMemory(const void *haystack, size_t haystacklen,
|
|
|
|
const void *needle, size_t needlelen);
|
|
|
|
|
2017-08-27 23:20:09 +00:00
|
|
|
std::string CloneArgsWithoutX(const Vector<std::string> &Args,
|
2017-08-21 23:25:50 +00:00
|
|
|
const char *X1, const char *X2);
|
|
|
|
|
2017-08-27 23:20:09 +00:00
|
|
|
inline std::string CloneArgsWithoutX(const Vector<std::string> &Args,
|
2017-08-21 23:25:50 +00:00
|
|
|
const char *X) {
|
|
|
|
return CloneArgsWithoutX(Args, X, X);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::pair<std::string, std::string> SplitBefore(std::string X,
|
|
|
|
std::string S) {
|
|
|
|
auto Pos = S.find(X);
|
|
|
|
if (Pos == std::string::npos)
|
|
|
|
return std::make_pair(S, "");
|
|
|
|
return std::make_pair(S.substr(0, Pos), S.substr(Pos));
|
|
|
|
}
|
|
|
|
|
2019-10-29 15:38:51 -07:00
|
|
|
void DiscardOutput(int Fd);
|
|
|
|
|
2017-08-21 23:25:50 +00:00
|
|
|
std::string DisassembleCmd(const std::string &FileName);
|
|
|
|
|
|
|
|
std::string SearchRegexCmd(const std::string &Regex);
|
|
|
|
|
2021-04-01 23:20:35 -07:00
|
|
|
uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial = 0);
|
2017-08-21 23:25:50 +00:00
|
|
|
|
[crt][fuzzer] Fix up various numeric conversions
Attempting to build a standalone libFuzzer in Fuchsia's default toolchain for the purpose of cross-compiling the unit tests revealed a number of not-quite-proper type conversions. Fuchsia's toolchain include `-std=c++17` and `-Werror`, among others, leading to many errors like `-Wshorten-64-to-32`, `-Wimplicit-float-conversion`, etc.
Most of these have been addressed by simply making the conversion explicit with a `static_cast`. These typically fell into one of two categories: 1) conversions between types where high precision isn't critical, e.g. the "energy" calculations for `InputInfo`, and 2) conversions where the values will never reach the bits being truncated, e.g. `DftTimeInSeconds` is not going to exceed 136 years.
The major exception to this is the number of features: there are several places that treat features as `size_t`, and others as `uint32_t`. This change makes the decision to cap the features at 32 bits. The maximum value of a feature as produced by `TracePC::CollectFeatures` is roughly:
(NumPCsInPCTables + ValueBitMap::kMapSizeInBits + ExtraCountersBegin() - ExtraCountersEnd() + log2(SIZE_MAX)) * 8
It's conceivable for extremely large targets and/or extra counters that this limit could be reached. This shouldn't break fuzzing, but it will cause certain features to collide and lower the fuzzers overall precision. To address this, this change adds a warning to TracePC::PrintModuleInfo about excessive feature size if it is detected, and recommends refactoring the fuzzer into several smaller ones.
Reviewed By: morehouse
Differential Revision: https://reviews.llvm.org/D97992
2021-03-11 16:00:53 -08:00
|
|
|
inline size_t Log(size_t X) {
|
|
|
|
return static_cast<size_t>((sizeof(unsigned long long) * 8) - Clzll(X) - 1);
|
|
|
|
}
|
2017-12-12 23:11:28 +00:00
|
|
|
|
2019-01-30 06:15:52 +00:00
|
|
|
inline size_t PageSize() { return 4096; }
|
|
|
|
inline uint8_t *RoundUpByPage(uint8_t *P) {
|
|
|
|
uintptr_t X = reinterpret_cast<uintptr_t>(P);
|
|
|
|
size_t Mask = PageSize() - 1;
|
|
|
|
X = (X + Mask) & ~Mask;
|
|
|
|
return reinterpret_cast<uint8_t *>(X);
|
|
|
|
}
|
|
|
|
inline uint8_t *RoundDownByPage(uint8_t *P) {
|
|
|
|
uintptr_t X = reinterpret_cast<uintptr_t>(P);
|
|
|
|
size_t Mask = PageSize() - 1;
|
|
|
|
X = X & ~Mask;
|
|
|
|
return reinterpret_cast<uint8_t *>(X);
|
|
|
|
}
|
|
|
|
|
2020-07-30 20:07:11 +02:00
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
|
template <typename T> T HostToLE(T X) { return X; }
|
|
|
|
#else
|
|
|
|
template <typename T> T HostToLE(T X) { return Bswap(X); }
|
|
|
|
#endif
|
|
|
|
|
2017-08-21 23:25:50 +00:00
|
|
|
} // namespace fuzzer
|
|
|
|
|
|
|
|
#endif // LLVM_FUZZER_UTIL_H
|