4500行之后注释+gcc #2

Open
pvsq2fh7g wants to merge 8 commits from developer into develop_ShangShuo

File diff suppressed because it is too large Load Diff

@ -14,6 +14,8 @@
limitations under the License. limitations under the License.
*/ */
// 这部分是版权声明和许可证信息说明这个文件是在Apache License 2.0下发布的。
/* /*
american fuzzy lop - wrapper for GCC and clang american fuzzy lop - wrapper for GCC and clang
---------------------------------------------- ----------------------------------------------
@ -38,7 +40,7 @@
specify its location via AFL_CC or AFL_CXX. specify its location via AFL_CC or AFL_CXX.
*/ */
// 这部分是注释,提供了关于这个程序的概述和使用说明。
#define AFL_MAIN #define AFL_MAIN
#include "config.h" #include "config.h"
@ -51,6 +53,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
// 这些是包含的头文件其中一些是AFL自己的头文件其他的是C标准库的头文件
static u8* as_path; /* Path to the AFL 'as' wrapper */ static u8* as_path; /* Path to the AFL 'as' wrapper */
static u8** cc_params; /* Parameters passed to the real CC */ static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */ static u32 cc_par_cnt = 1; /* Param count, including argv0 */
@ -58,11 +62,14 @@ static u8 be_quiet, /* Quiet mode */
clang_mode; /* Invoked as afl-clang*? */ clang_mode; /* Invoked as afl-clang*? */
// 这些是全局变量声明。`as_path`存储AFL汇编器的路径`cc_params`存储传递给实际编译器的参数,`cc_par_cnt`是参数计数器,`be_quiet`用于控制
// 是否静默模式,`clang_mode`指示是否以`afl-clang`或`afl-clang++`模式调用。
/* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived /* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
from argv[0]. If that fails, abort. */ from argv[0]. If that fails, abort. */
static void find_as(u8* argv0) { static void find_as(u8* argv0) {
// 这个函数尝试在AFL_PATH环境变量指定的路径或从argv[0]派生的路径中找到AFL的“假”GNU汇编器。如果找不到程序将终止。
u8 *afl_path = getenv("AFL_PATH"); u8 *afl_path = getenv("AFL_PATH");
u8 *slash, *tmp; u8 *slash, *tmp;
@ -116,31 +123,32 @@ static void find_as(u8* argv0) {
/* Copy argv to cc_params, making the necessary edits. */ /* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char** argv) { static void edit_params(u32 argc, char** argv) {
//定义了一个函数edit_params它接受两个参数argc是参数的数量argv是参数的数组。
u8 fortify_set = 0, asan_set = 0; u8 fortify_set = 0, asan_set = 0;//声明两个变量fortify_set和asan_set用于跟踪是否已经设置了FORTIFY_SOURCE和address sanitizerASan标志
u8 *name; u8 *name;//用于存储程序的名称
#if defined(__FreeBSD__) && defined(__x86_64__) #if defined(__FreeBSD__) && defined(__x86_64__)
u8 m32_set = 0; u8 m32_set = 0;
#endif #endif
cc_params = ck_alloc((argc + 128) * sizeof(u8*)); cc_params = ck_alloc((argc + 128) * sizeof(u8*));//分配内存以存储修改后的参数列表大小为argc + 128个u8*类型的指针。
name = strrchr(argv[0], '/'); name = strrchr(argv[0], '/');//找到argv[0](程序的路径)中最后一个'/'字符,这通常用于获取程序的名称。
if (!name) name = argv[0]; else name++; if (!name) name = argv[0]; else name++;//如果name为NULL即argv[0]中没有'/'则name指向argv[0]的开始。否则name向前移动一个字符跳过'/'。
if (!strncmp(name, "afl-clang", 9)) { if (!strncmp(name, "afl-clang", 9)) {
clang_mode = 1; clang_mode = 1;//检查程序名称是否以"afl-clang"开头如果是设置clang_mode标志为1
setenv(CLANG_ENV_VAR, "1", 1); setenv(CLANG_ENV_VAR, "1", 1);//设置环境变量CLANG_ENV_VAR为"1"这可能用于通知其他部分的AFL工具链正在使用Clang。
if (!strcmp(name, "afl-clang++")) { if (!strcmp(name, "afl-clang++")) {
u8* alt_cxx = getenv("AFL_CXX"); u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";//如果AFL_CXX设置将其值作为第一个参数否则使用"clang++"。
} else { } else {
u8* alt_cc = getenv("AFL_CC"); u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";//否则尝试获取环境变量AFL_CC的值。
} }
} else { } else {
@ -152,13 +160,13 @@ static void edit_params(u32 argc, char** argv) {
binaries. Meh. */ binaries. Meh. */
#ifdef __APPLE__ #ifdef __APPLE__
//在Apple系统上根据程序名称设置不同的编译器。如果AFL_CXX、AFL_GCJ或AFL_CC环境变量设置使用它们的值否则使用默认的编译器名称
if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX"); if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX");
else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ"); else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ");
else cc_params[0] = getenv("AFL_CC"); else cc_params[0] = getenv("AFL_CC");
if (!cc_params[0]) { if (!cc_params[0]) {
//输出错误信息指出在MacOS X上需要设置AFL_CC或AFL_CXX环境变量。
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
"On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n" "On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n"
" 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n" " 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n"
@ -169,7 +177,7 @@ static void edit_params(u32 argc, char** argv) {
} }
#else #else
//对于非Apple系统根据程序名称设置不同的编译器。如果相应的环境变量设置使用它们的值否则使用默认的编译器名称。
if (!strcmp(name, "afl-g++")) { if (!strcmp(name, "afl-g++")) {
u8* alt_cxx = getenv("AFL_CXX"); u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++"; cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++";
@ -188,27 +196,27 @@ static void edit_params(u32 argc, char** argv) {
while (--argc) { while (--argc) {
u8* cur = *(++argv); u8* cur = *(++argv);
if (!strncmp(cur, "-B", 2)) { if (!strncmp(cur, "-B", 2)) {//如果当前参数以"-B"开头,输出警告信息,并跳过后续参数(如果当前参数后面紧跟着的是编译器的路径)。
if (!be_quiet) WARNF("-B is already set, overriding"); if (!be_quiet) WARNF("-B is already set, overriding");//如果程序不在静默模式,输出警告信息。
if (!cur[2] && argc > 1) { argc--; argv++; } if (!cur[2] && argc > 1) { argc--; argv++; }//如果-B后面紧跟着的是编译器的路径跳过这个路径。
continue; continue;
} }
if (!strcmp(cur, "-integrated-as")) continue; if (!strcmp(cur, "-integrated-as")) continue;//如果参数是"-integrated-as",跳过它。
if (!strcmp(cur, "-pipe")) continue; if (!strcmp(cur, "-pipe")) continue;//如果参数是"-pipe",跳过它。
#if defined(__FreeBSD__) && defined(__x86_64__) #if defined(__FreeBSD__) && defined(__x86_64__)
if (!strcmp(cur, "-m32")) m32_set = 1; if (!strcmp(cur, "-m32")) m32_set = 1;
#endif #endif
if (!strcmp(cur, "-fsanitize=address") || if (!strcmp(cur, "-fsanitize=address") ||
!strcmp(cur, "-fsanitize=memory")) asan_set = 1; !strcmp(cur, "-fsanitize=memory")) asan_set = 1;//如果参数是"-fsanitize=address"或"-fsanitize=memory"设置asan_set标志。
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;//如果参数包含"FORTIFY_SOURCE"设置fortify_set标志。
cc_params[cc_par_cnt++] = cur; cc_params[cc_par_cnt++] = cur;
@ -216,9 +224,11 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-B"; cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = as_path; cc_params[cc_par_cnt++] = as_path;
//向参数列表中添加"-B"和AFL汇编器的路径。
if (clang_mode) if (clang_mode)
cc_params[cc_par_cnt++] = "-no-integrated-as"; cc_params[cc_par_cnt++] = "-no-integrated-as";//如果clang_mode标志设置向参数列表中添加`"-no-integrated-as"
if (getenv("AFL_HARDEN")) { if (getenv("AFL_HARDEN")) {
@ -229,38 +239,38 @@ static void edit_params(u32 argc, char** argv) {
} }
if (asan_set) { if (asan_set) {//检查是否设置了asan_set标志。
/* Pass this on to afl-as to adjust map density. */ /* Pass this on to afl-as to adjust map density. */
setenv("AFL_USE_ASAN", "1", 1); setenv("AFL_USE_ASAN", "1", 1);//如果设置设置环境变量AFL_USE_ASAN为"1"
} else if (getenv("AFL_USE_ASAN")) { } else if (getenv("AFL_USE_ASAN")) {//如果asan_set标志未设置但设置了环境变量AFL_USE_ASAN。
if (getenv("AFL_USE_MSAN")) if (getenv("AFL_USE_MSAN"))
FATAL("ASAN and MSAN are mutually exclusive"); FATAL("ASAN and MSAN are mutually exclusive");//如果同时设置了AFL_USE_MSAN输出错误信息并终止程序。
if (getenv("AFL_HARDEN")) if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive"); FATAL("ASAN and AFL_HARDEN are mutually exclusive");//如果同时设置了AFL_HARDEN输出错误信息并终止程序。
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=address"; cc_params[cc_par_cnt++] = "-fsanitize=address";//向参数列表中添加"-U_FORTIFY_SOURCE"和"-fsanitize=address"。
} else if (getenv("AFL_USE_MSAN")) { } else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN")) if (getenv("AFL_USE_ASAN"))
FATAL("ASAN and MSAN are mutually exclusive"); FATAL("ASAN and MSAN are mutually exclusive");//如果同时设置了AFL_USE_ASAN输出错误信息并终止程序。
if (getenv("AFL_HARDEN")) if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive"); FATAL("MSAN and AFL_HARDEN are mutually exclusive");//如果同时设置了AFL_HARDEN输出错误信息并终止程序。
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=memory"; cc_params[cc_par_cnt++] = "-fsanitize=memory";//向参数列表中添加"-U_FORTIFY_SOURCE"和"-fsanitize=memory"。
} }
if (!getenv("AFL_DONT_OPTIMIZE")) { if (!getenv("AFL_DONT_OPTIMIZE")) {//检查是否设置了环境变量AFL_DONT_OPTIMIZE。
#if defined(__FreeBSD__) && defined(__x86_64__) #if defined(__FreeBSD__) && defined(__x86_64__)
@ -269,22 +279,23 @@ static void edit_params(u32 argc, char** argv) {
that bug. */ that bug. */
if (!clang_mode || !m32_set) if (!clang_mode || !m32_set)
cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-g";//如果不是Clang模式或没有设置m32_set标志向参数列表中添加"-g"。
#else #else
cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-g";
#endif #endif//结束#if defined(__FreeBSD__) && defined(__x86_64__)条件编译块。
cc_params[cc_par_cnt++] = "-O3"; cc_params[cc_par_cnt++] = "-O3";
cc_params[cc_par_cnt++] = "-funroll-loops"; cc_params[cc_par_cnt++] = "-funroll-loops";//向参数列表中添加"-O3"和"-funroll-loops",这些是优化选项。
/* Two indicators that you're building for fuzzing; one of them is /* Two indicators that you're building for fuzzing; one of them is
AFL-specific, the other is shared with libfuzzer. */ AFL-specific, the other is shared with libfuzzer. */
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
//向参数列表中添加两个宏定义,这些宏定义指示编译器代码将用于模糊测试。
} }
@ -297,7 +308,7 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
//如果设置,向参数列表中添加一系列"-fno-builtin-*"选项,这些选项禁用编译器的内置函数。
} }
cc_params[cc_par_cnt] = NULL; cc_params[cc_par_cnt] = NULL;
@ -306,7 +317,7 @@ static void edit_params(u32 argc, char** argv) {
/* Main entry point */ /* Main entry point */
//最后是函数结束语,结束函数定义。
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (isatty(2) && !getenv("AFL_QUIET")) { if (isatty(2) && !getenv("AFL_QUIET")) {

@ -1,35 +1,29 @@
/* /*
Copyright 2015 Google LLC All rights reserved. 2015 Google LLC
Licensed under the Apache License, Version 2.0 (the "License"); Apache License, 2.0
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 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/ */
/* /*
american fuzzy lop - free CPU gizmo - CPU
----------------------------------- -----------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com> Michal Zalewski <lcamtuf@google.com>
This tool provides a fairly accurate measurement of CPU preemption rate. CPU
It is meant to complement the quick-and-dirty load average widget shown afl-fuzz UIdocs/parallel_fuzzing.txt
in the afl-fuzz UI. See docs/parallel_fuzzing.txt for more info.
For some work loads, the tool may actually suggest running more instances CPUI/O100% CPU
than you have CPU cores. This can happen if the tested program is spending
a portion of its run time waiting for I/O, rather than being 100%
CPU-bound.
The idea for the getrusage()-based approach comes from Jakub Wilk. getrusage()Jakub Wilk
*/ */
#define AFL_MAIN #define AFL_MAIN
@ -55,119 +49,151 @@
#endif /* __linux__ */ #endif /* __linux__ */
/* Get unix time in microseconds. */ /*
Unix
*/
static u64 get_cur_time_us(void) { static u64 get_cur_time_us(void) {
// 定义一个timeval结构体变量tv用于存储当前时间
struct timeval tv; struct timeval tv;
// 定义一个timezone结构体变量tz用于存储时区信息
struct timezone tz; struct timezone tz;
// 使用gettimeofday函数获取当前时间并存储到tv和tz中
gettimeofday(&tv, &tz); gettimeofday(&tv, &tz);
// 将秒转换为微秒,并加上微秒部分,返回当前时间的微秒值
return (tv.tv_sec * 1000000ULL) + tv.tv_usec; return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
} }
/*
/* Get CPU usage in microseconds. */ CPU使
*/
static u64 get_cpu_usage_us(void) { static u64 get_cpu_usage_us(void) {
// 定义一个rusage结构体变量u用于存储资源使用情况
struct rusage u; struct rusage u;
// 使用getrusage函数获取当前进程的资源使用情况并存储到u中
getrusage(RUSAGE_SELF, &u); getrusage(RUSAGE_SELF, &u);
// 计算用户态和核心态的总使用时间(微秒),并返回
return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec + return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec +
(u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec; (u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec;
} }
/* Measure preemption rate. */ /*
*/
static u32 measure_preemption(u32 target_ms) { static u32 measure_preemption(u32 target_ms) {
// 定义两个易失性变量,用于循环测试
static volatile u32 v1, v2; static volatile u32 v1, v2;
// 定义变量用于存储开始和结束的时间微秒以及CPU使用时间
u64 st_t, en_t, st_c, en_c, real_delta, slice_delta; u64 st_t, en_t, st_c, en_c, real_delta, slice_delta;
// 定义循环重复次数
s32 loop_repeats = 0; s32 loop_repeats = 0;
// 获取当前时间(微秒)
st_t = get_cur_time_us(); st_t = get_cur_time_us();
// 获取当前CPU使用时间微秒
st_c = get_cpu_usage_us(); st_c = get_cpu_usage_us();
repeat_loop: repeat_loop:
// 设置v1为一个忙循环的计数
v1 = CTEST_BUSY_CYCLES; v1 = CTEST_BUSY_CYCLES;
// 执行忙循环同时v2自增
while (v1--) v2++; while (v1--) v2++;
// 调用sched_yield()让出CPU
sched_yield(); sched_yield();
// 再次获取当前时间(微秒)
en_t = get_cur_time_us(); en_t = get_cur_time_us();
// 如果当前时间与开始时间的差小于目标时间(毫秒转换为微秒),则增加循环次数并继续循环
if (en_t - st_t < target_ms * 1000) { if (en_t - st_t < target_ms * 1000) {
loop_repeats++; loop_repeats++;
goto repeat_loop; goto repeat_loop;
} }
/* Let's see what percentage of this time we actually had a chance to /* 让我们看看这段时间里我们实际上有多少百分比的机会运行,
run, and how much time was spent in the penalty box. */ */
// 获取当前CPU使用时间微秒
en_c = get_cpu_usage_us(); en_c = get_cpu_usage_us();
// 计算实际时间差毫秒和CPU使用时间差毫秒
real_delta = (en_t - st_t) / 1000; real_delta = (en_t - st_t) / 1000;
slice_delta = (en_c - st_c) / 1000; slice_delta = (en_c - st_c) / 1000;
// 返回实际时间差占CPU使用时间差的百分比即抢占率
return real_delta * 100 / slice_delta; return real_delta * 100 / slice_delta;
} }
/*
/* Do the benchmark thing. */
*/
int main(int argc, char** argv) { int main(int argc, char** argv) {
#ifdef HAVE_AFFINITY #ifdef HAVE_AFFINITY
// 获取在线的CPU核心数
u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN), u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN),
// 初始化空闲CPU和可能可用CPU的计数器
idle_cpus = 0, maybe_cpus = 0, i; idle_cpus = 0, maybe_cpus = 0, i;
// 打印欢迎信息和版本号
SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
// 打印测量每个核心抢占率所需的时间
ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...", ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...",
((double)CTEST_CORE_TRG_MS) / 1000); ((double)CTEST_CORE_TRG_MS) / 1000);
// 遍历每个CPU核心
for (i = 0; i < cpu_cnt; i++) { for (i = 0; i < cpu_cnt; i++) {
// 创建子进程
s32 fr = fork(); s32 fr = fork();
// 如果fork失败则打印错误信息并退出
if (fr < 0) PFATAL("fork failed"); if (fr < 0) PFATAL("fork failed");
// 如果是子进程,则执行以下操作
if (!fr) { if (!fr) {
// 定义CPU集合
cpu_set_t c; cpu_set_t c;
// 定义CPU使用率百分比
u32 util_perc; u32 util_perc;
// 初始化CPU集合
CPU_ZERO(&c); CPU_ZERO(&c);
// 将当前核心加入CPU集合
CPU_SET(i, &c); CPU_SET(i, &c);
// 如果设置CPU亲和性失败则打印错误信息并退出
if (sched_setaffinity(0, sizeof(c), &c)) if (sched_setaffinity(0, sizeof(c), &c))
PFATAL("sched_setaffinity failed for cpu %d", i); PFATAL("sched_setaffinity failed for cpu %d", i);
// 测量抢占率
util_perc = measure_preemption(CTEST_CORE_TRG_MS); util_perc = measure_preemption(CTEST_CORE_TRG_MS);
// 如果使用率低于110%,则标记为核心可用,并退出
if (util_perc < 110) { if (util_perc < 110) {
SAYF(" Core #%u: " cLGN "AVAILABLE" cRST "(%u%%)\n", i, util_perc);
SAYF(" Core #%u: " cLGN "AVAILABLE " cRST "(%u%%)\n", i, util_perc);
exit(0); exit(0);
} else if (util_perc < 250) { } else if (util_perc < 250) {
// 如果使用率低于250%,则标记为核心需要谨慎,并退出
SAYF(" Core #%u: " cYEL "CAUTION " cRST "(%u%%)\n", i, util_perc); SAYF(" Core #%u: " cYEL "CAUTION" cRST "(%u%%)\n", i, util_perc);
exit(1); exit(1);
} }
SAYF(" Core #%u: " cLRD "OVERBOOKED " cRST "(%u%%)\n" cRST, i, // 如果使用率高于250%,则标记为核心过载,并退出
SAYF(" Core #%u: " cLRD "OVERBOOKED" cRST "(%u%%)\n" cRST, i,
util_perc); util_perc);
exit(2); exit(2);
@ -175,44 +201,35 @@ int main(int argc, char** argv) {
} }
// 等待子进程结束,并统计空闲和可能可用的核心数
for (i = 0; i < cpu_cnt; i++) { for (i = 0; i < cpu_cnt; i++) {
int ret; int ret;
if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed"); if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed");
if (WEXITSTATUS(ret) == 0) idle_cpus++; if (WEXITSTATUS(ret) == 0) idle_cpus++;
if (WEXITSTATUS(ret) <= 1) maybe_cpus++; if (WEXITSTATUS(ret) <= 1) maybe_cpus++;
} }
// 根据空闲和可能可用的核心数打印结果
SAYF(cGRA "\n>>> "); SAYF(cGRA "\n>>> ");
if (idle_cpus) { if (idle_cpus) {
if (maybe_cpus == idle_cpus) { if (maybe_cpus == idle_cpus) {
SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.", SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.",
idle_cpus, idle_cpus > 1 ? "s" : ""); idle_cpus, idle_cpus > 1 ? "s" : "");
} else { } else {
SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.", SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.",
idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : ""); idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : "");
} }
SAYF(cGRA " <<<" cRST "\n\n"); SAYF(cGRA " <<<" cRST "\n\n");
return 0; return 0;
} }
if (maybe_cpus) { if (maybe_cpus) {
SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.", SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.",
maybe_cpus, maybe_cpus > 1 ? "s" : ""); maybe_cpus, maybe_cpus > 1 ? "s" : "");
SAYF(cGRA " <<<" cRST "\n\n"); SAYF(cGRA " <<<" cRST "\n\n");
return 1; return 1;
} }
SAYF(cLRD "FAIL: " cRST "All cores are overbooked."); SAYF(cLRD "FAIL: " cRST "All cores are overbooked.");
@ -221,38 +238,35 @@ int main(int argc, char** argv) {
#else #else
// 如果没有CPU亲和性支持则执行总体抢占率的测量
u32 util_perc; u32 util_perc;
SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
/* Run a busy loop for CTEST_TARGET_MS. */ /* 运行一个忙循环持续CTEST_TARGET_MS毫秒。 */
ACTF("Measuring gross preemption rate (this will take %0.02f sec)...", ACTF("Measuring gross preemption rate (this will take %0.02f sec)...",
((double)CTEST_TARGET_MS) / 1000); ((double)CTEST_TARGET_MS) / 1000);
// 测量抢占率
util_perc = measure_preemption(CTEST_TARGET_MS); util_perc = measure_preemption(CTEST_TARGET_MS);
/* Deliver the final verdict. */ /* 输出最终结果。 */
SAYF(cGRA "\n>>> "); SAYF(cGRA "\n>>> ");
if (util_perc < 105) { if (util_perc < 105) {
SAYF(cLGN "PASS: " cRST "You can probably run additional processes."); SAYF(cLGN "PASS: " cRST "You can probably run additional processes.");
} else if (util_perc < 130) { } else if (util_perc < 130) {
SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).", SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).",
util_perc); util_perc);
} else { } else {
SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc); SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc);
} }
SAYF(cGRA " <<<" cRST "\n\n"); SAYF(cGRA " <<<" cRST "\n\n");
// 返回结果代码
return (util_perc > 105) + (util_perc > 130); return (util_perc > 105) + (util_perc > 130);
#endif /* ^HAVE_AFFINITY */ #endif /* ^HAVE_AFFINITY */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,357 @@
/*
Copyright 2013 Google LLC 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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// 这部分是版权声明和许可证信息说明这个文件是在Apache License 2.0下发布的。
/*
american fuzzy lop - wrapper for GCC and clang
----------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
This program is a drop-in replacement for GCC or clang. The most common way
of using it is to pass the path to afl-gcc or afl-clang via CC when invoking
./configure.
(Of course, use CXX and point it to afl-g++ / afl-clang++ for C++ code.)
The wrapper needs to know the path to afl-as (renamed to 'as'). The default
is /usr/local/lib/afl/. A convenient way to specify alternative directories
would be to set AFL_PATH.
If AFL_HARDEN is set, the wrapper will compile the target app with various
hardening options that may help detect memory management issues more
reliably. You can also specify AFL_USE_ASAN to enable ASAN.
If you want to call a non-default compiler as a next step of the chain,
specify its location via AFL_CC or AFL_CXX.
*/
// 这部分是注释,提供了关于这个程序的概述和使用说明。
#define AFL_MAIN
#include "config.h"
#include "types.h"
#include "debug.h"
#include "alloc-inl.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
// 这些是包含的头文件其中一些是AFL自己的头文件其他的是C标准库的头文件
static u8* as_path; /* Path to the AFL 'as' wrapper */
static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
static u8 be_quiet, /* Quiet mode */
clang_mode; /* Invoked as afl-clang*? */
// 这些是全局变量声明。`as_path`存储AFL汇编器的路径`cc_params`存储传递给实际编译器的参数,`cc_par_cnt`是参数计数器,`be_quiet`用于控制
// 是否静默模式,`clang_mode`指示是否以`afl-clang`或`afl-clang++`模式调用。
/* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
from argv[0]. If that fails, abort. */
static void find_as(u8* argv0) {
// 这个函数尝试在AFL_PATH环境变量指定的路径或从argv[0]派生的路径中找到AFL的“假”GNU汇编器。如果找不到程序将终止。
u8 *afl_path = getenv("AFL_PATH");
u8 *slash, *tmp;
if (afl_path) {
tmp = alloc_printf("%s/as", afl_path);
if (!access(tmp, X_OK)) {
as_path = afl_path;
ck_free(tmp);
return;
}
ck_free(tmp);
}
slash = strrchr(argv0, '/');
if (slash) {
u8 *dir;
*slash = 0;
dir = ck_strdup(argv0);
*slash = '/';
tmp = alloc_printf("%s/afl-as", dir);
if (!access(tmp, X_OK)) {
as_path = dir;
ck_free(tmp);
return;
}
ck_free(tmp);
ck_free(dir);
}
if (!access(AFL_PATH "/as", X_OK)) {
as_path = AFL_PATH;
return;
}
FATAL("Unable to find AFL wrapper binary for 'as'. Please set AFL_PATH");
}
/* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char** argv) {
//定义了一个函数edit_params它接受两个参数argc是参数的数量argv是参数的数组。
u8 fortify_set = 0, asan_set = 0;//声明两个变量fortify_set和asan_set用于跟踪是否已经设置了FORTIFY_SOURCE和address sanitizerASan标志
u8 *name;//用于存储程序的名称
#if defined(__FreeBSD__) && defined(__x86_64__)
u8 m32_set = 0;
#endif
cc_params = ck_alloc((argc + 128) * sizeof(u8*));//分配内存以存储修改后的参数列表大小为argc + 128个u8*类型的指针。
name = strrchr(argv[0], '/');//找到argv[0](程序的路径)中最后一个'/'字符,这通常用于获取程序的名称。
if (!name) name = argv[0]; else name++;//如果name为NULL即argv[0]中没有'/'则name指向argv[0]的开始。否则name向前移动一个字符跳过'/'。
if (!strncmp(name, "afl-clang", 9)) {
clang_mode = 1;//检查程序名称是否以"afl-clang"开头如果是设置clang_mode标志为1
setenv(CLANG_ENV_VAR, "1", 1);//设置环境变量CLANG_ENV_VAR为"1"这可能用于通知其他部分的AFL工具链正在使用Clang。
if (!strcmp(name, "afl-clang++")) {
u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";//如果AFL_CXX设置将其值作为第一个参数否则使用"clang++"。
} else {
u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";//否则尝试获取环境变量AFL_CC的值。
}
} else {
/* With GCJ and Eclipse installed, you can actually compile Java! The
instrumentation will work (amazingly). Alas, unhandled exceptions do
not call abort(), so afl-fuzz would need to be modified to equate
non-zero exit codes with crash conditions when working with Java
binaries. Meh. */
#ifdef __APPLE__
//在Apple系统上根据程序名称设置不同的编译器。如果AFL_CXX、AFL_GCJ或AFL_CC环境变量设置使用它们的值否则使用默认的编译器名称
if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX");
else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ");
else cc_params[0] = getenv("AFL_CC");
if (!cc_params[0]) {
//输出错误信息指出在MacOS X上需要设置AFL_CC或AFL_CXX环境变量。
SAYF("\n" cLRD "[-] " cRST
"On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n"
" 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n"
" set AFL_CC or AFL_CXX to specify the correct path to that compiler.\n");
FATAL("AFL_CC or AFL_CXX required on MacOS X");
}
#else
//对于非Apple系统根据程序名称设置不同的编译器。如果相应的环境变量设置使用它们的值否则使用默认的编译器名称。
if (!strcmp(name, "afl-g++")) {
u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++";
} else if (!strcmp(name, "afl-gcj")) {
u8* alt_cc = getenv("AFL_GCJ");
cc_params[0] = alt_cc ? alt_cc : (u8*)"gcj";
} else {
u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc";
}
#endif /* __APPLE__ */
}
while (--argc) {
u8* cur = *(++argv);
if (!strncmp(cur, "-B", 2)) {//如果当前参数以"-B"开头,输出警告信息,并跳过后续参数(如果当前参数后面紧跟着的是编译器的路径)。
if (!be_quiet) WARNF("-B is already set, overriding");//如果程序不在静默模式,输出警告信息。
if (!cur[2] && argc > 1) { argc--; argv++; }//如果-B后面紧跟着的是编译器的路径跳过这个路径。
continue;
}
if (!strcmp(cur, "-integrated-as")) continue;//如果参数是"-integrated-as",跳过它。
if (!strcmp(cur, "-pipe")) continue;//如果参数是"-pipe",跳过它。
#if defined(__FreeBSD__) && defined(__x86_64__)
if (!strcmp(cur, "-m32")) m32_set = 1;
#endif
if (!strcmp(cur, "-fsanitize=address") ||
!strcmp(cur, "-fsanitize=memory")) asan_set = 1;//如果参数是"-fsanitize=address"或"-fsanitize=memory"设置asan_set标志。
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;//如果参数包含"FORTIFY_SOURCE"设置fortify_set标志。
cc_params[cc_par_cnt++] = cur;
}
cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = as_path;
//向参数列表中添加"-B"和AFL汇编器的路径。
if (clang_mode)
cc_params[cc_par_cnt++] = "-no-integrated-as";//如果clang_mode标志设置向参数列表中添加`"-no-integrated-as"
if (getenv("AFL_HARDEN")) {
cc_params[cc_par_cnt++] = "-fstack-protector-all";
if (!fortify_set)
cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
}
if (asan_set) {//检查是否设置了asan_set标志。
/* Pass this on to afl-as to adjust map density. */
setenv("AFL_USE_ASAN", "1", 1);//如果设置设置环境变量AFL_USE_ASAN为"1"
} else if (getenv("AFL_USE_ASAN")) {//如果asan_set标志未设置但设置了环境变量AFL_USE_ASAN。
if (getenv("AFL_USE_MSAN"))
FATAL("ASAN and MSAN are mutually exclusive");//如果同时设置了AFL_USE_MSAN输出错误信息并终止程序。
if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive");//如果同时设置了AFL_HARDEN输出错误信息并终止程序。
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=address";//向参数列表中添加"-U_FORTIFY_SOURCE"和"-fsanitize=address"。
} else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN"))
FATAL("ASAN and MSAN are mutually exclusive");//如果同时设置了AFL_USE_ASAN输出错误信息并终止程序。
if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive");//如果同时设置了AFL_HARDEN输出错误信息并终止程序。
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=memory";//向参数列表中添加"-U_FORTIFY_SOURCE"和"-fsanitize=memory"。
}
if (!getenv("AFL_DONT_OPTIMIZE")) {//检查是否设置了环境变量AFL_DONT_OPTIMIZE。
#if defined(__FreeBSD__) && defined(__x86_64__)
/* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself
works OK. This has nothing to do with us, but let's avoid triggering
that bug. */
if (!clang_mode || !m32_set)
cc_params[cc_par_cnt++] = "-g";//如果不是Clang模式或没有设置m32_set标志向参数列表中添加"-g"。
#else
cc_params[cc_par_cnt++] = "-g";
#endif//结束#if defined(__FreeBSD__) && defined(__x86_64__)条件编译块。
cc_params[cc_par_cnt++] = "-O3";
cc_params[cc_par_cnt++] = "-funroll-loops";//向参数列表中添加"-O3"和"-funroll-loops",这些是优化选项。
/* Two indicators that you're building for fuzzing; one of them is
AFL-specific, the other is shared with libfuzzer. */
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
//向参数列表中添加两个宏定义,这些宏定义指示编译器代码将用于模糊测试。
}
if (getenv("AFL_NO_BUILTIN")) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
//如果设置,向参数列表中添加一系列"-fno-builtin-*"选项,这些选项禁用编译器的内置函数。
}
cc_params[cc_par_cnt] = NULL;
}
/* Main entry point */
//最后是函数结束语,结束函数定义。
int main(int argc, char** argv) {
if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(cCYA "afl-cc " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
} else be_quiet = 1;
if (argc < 2) {
SAYF("\n"
"This is a helper application for afl-fuzz. It serves as a drop-in replacement\n"
"for gcc or clang, letting you recompile third-party code with the required\n"
"runtime instrumentation. A common use pattern would be one of the following:\n\n"
" CC=%s/afl-gcc ./configure\n"
" CXX=%s/afl-g++ ./configure\n\n"
"You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS.\n"
"Setting AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
BIN_PATH, BIN_PATH);
exit(1);
}
find_as(argv[0]);
edit_params(argc, argv);
execvp(cc_params[0], (char**)cc_params);
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
return 0;
}
Loading…
Cancel
Save