yinao #7

Merged
phq7r92sf merged 1 commits from dev-yinao into main 9 months ago

@ -0,0 +1,6 @@
{
"files.associations": {
"stdio.h": "c",
"alloc-inl.h": "c"
}
}

@ -1,50 +1,50 @@
/* /*
Copyright 2013 Google LLC All rights reserved. Copyright 2013 Google LLC All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at: 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 Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
/* /*
american fuzzy lop - wrapper for GNU as american fuzzy lop - wrapper for GNU as
--------------------------------------- ---------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com> Written and maintained by Michal Zalewski <lcamtuf@google.com>
The sole purpose of this wrapper is to preprocess assembly files generated The sole purpose of this wrapper is to preprocess assembly files generated
by GCC / clang and inject the instrumentation bits included from afl-as.h. It by GCC / clang and inject the instrumentation bits included from afl-as.h. It
is automatically invoked by the toolchain when compiling programs using is automatically invoked by the toolchain when compiling programs using
afl-gcc / afl-clang. afl-gcc / afl-clang.
Note that it's an explicit non-goal to instrument hand-written assembly, Note that it's an explicit non-goal to instrument hand-written assembly,
be it in separate .s files or in __asm__ blocks. The only aspiration this be it in separate .s files or in __asm__ blocks. The only aspiration this
utility has right now is to be able to skip them gracefully and allow the utility has right now is to be able to skip them gracefully and allow the
compilation process to continue. compilation process to continue.
That said, see experimental/clang_asm_normalize/ for a solution that may That said, see experimental/clang_asm_normalize/ for a solution that may
allow clang users to make things work even with hand-crafted assembly. Just allow clang users to make things work even with hand-crafted assembly. Just
note that there is no equivalent for GCC. note that there is no equivalent for GCC.
*/ */
#define AFL_MAIN #define AFL_MAIN
#include "config.h" #include "config.h"
#include "types.h" #include "types.h"
#include "debug.h" #include "debug.h"
#include "alloc-inl.h" #include "alloc-inl.h"
#include "afl-as.h" #include "afl-as.h"
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -52,248 +52,233 @@
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/time.h> #include <sys/time.h>
static u8** as_params; /* Parameters passed to the real 'as' */ static u8** as_params; /* Parameters passed to the real 'as' */
static u8* input_file; /* Originally specified input file */ static u8* input_file; /* Originally specified input file */
static u8* modified_file; /* Instrumented file for the real 'as' */ static u8* modified_file; /* Instrumented file for the real 'as' */
static u8 be_quiet, /* Quiet mode (no stderr output) */ static u8 be_quiet, /* Quiet mode (no stderr output) */
clang_mode, /* Running in clang mode? */ clang_mode, /* Running in clang mode? */
pass_thru, /* Just pass data through? */ pass_thru, /* Just pass data through? */
just_version, /* Just show version? */ just_version, /* Just show version? */
sanitizer; /* Using ASAN / MSAN */ sanitizer; /* Using ASAN / MSAN */
static u32 inst_ratio = 100, /* Instrumentation probability (%) */ static u32 inst_ratio = 100, /* Instrumentation probability (%) */
as_par_cnt = 1; /* Number of params to 'as' */ as_par_cnt = 1; /* Number of params to 'as' */
/* If we don't find --32 or --64 in the command line, default to /* 如果命令行中没有找到 --32 或 --64 参数,则默认对编译该工具时使用的模式进行插桩。
instrumentation for whichever mode we were compiled with. This is not 使 */
perfect, but should do the trick for almost all use cases. */
#ifdef WORD_SIZE_64 #ifdef WORD_SIZE_64
static u8 use_64bit = 1; static u8 use_64bit = 1;
#else #else
static u8 use_64bit = 0; static u8 use_64bit = 0;
#ifdef __APPLE__ #ifdef __APPLE__
# error "Sorry, 32-bit Apple platforms are not supported." # error "Sorry, 32-bit Apple platforms are not supported."
#endif /* __APPLE__ */ #endif /* __APPLE__ */
#endif /* ^WORD_SIZE_64 */ #endif /* ^WORD_SIZE_64 */
/* Examine and modify parameters to pass to 'as'. Note that the file name /* 检查并修改传递给 'as' 的参数。注意 GCC 总是将文件名作为最后一个参数传递给 'as'
is always the last parameter passed by GCC, so we exploit this property */
to keep the code simple. */
static void edit_params(int argc, char** argv) { static void edit_params(int argc, char** argv) {
u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS");
u32 i; u32 i;
#ifdef __APPLE__ #ifdef __APPLE__
u8 use_clang_as = 0; u8 use_clang_as = 0;
/* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work /* 在 MacOS X 上Xcode cctool 'as' 驱动程序有点过时,无法处理由用户自己编译的较新版本的 clang
with the code generated by newer versions of clang that are hand-built 线http://goo.gl/HBWDtn.
by the user. See the thread here: http://goo.gl/HBWDtn.
使 clang AFL_AS 'clang -c' 'as -q'
To work around this, when using clang and running without AFL_AS .
specified, we will actually call 'clang -c' instead of 'as -q' to
compile the assembly file.
Nico Weber */
The tools aren't cmdline-compatible, but at least for now, we can
seemingly get away with this by making only very minor tweaks. Thanks
to Nico Weber for the idea. */
if (clang_mode && !afl_as) { if (clang_mode && !afl_as) {
use_clang_as = 1; use_clang_as = 1;
afl_as = getenv("AFL_CC"); afl_as = getenv("AFL_CC");
if (!afl_as) afl_as = getenv("AFL_CXX"); if (!afl_as) afl_as = getenv("AFL_CXX");
if (!afl_as) afl_as = "clang"; if (!afl_as) afl_as = "clang";
} }
#endif /* __APPLE__ */ #endif /* __APPLE__ */
/* Although this is not documented, GCC also uses TEMP and TMP when TMPDIR /* 虽然这在文档中没有提及,但 GCC 实际上也使用 TEMP 和 TMP当 TMPDIR 未设置时)。
is not set. We need to check these non-standard variables to properly pass_thru */
handle the pass_thru logic later on. */
if (!tmp_dir) tmp_dir = getenv("TEMP"); if (!tmp_dir) tmp_dir = getenv("TEMP");
if (!tmp_dir) tmp_dir = getenv("TMP"); if (!tmp_dir) tmp_dir = getenv("TMP");
if (!tmp_dir) tmp_dir = "/tmp"; if (!tmp_dir) tmp_dir = "/tmp";
as_params = ck_alloc((argc + 32) * sizeof(u8*)); as_params = ck_alloc((argc + 32) * sizeof(u8*));
as_params[0] = afl_as ? afl_as : (u8*)"as"; as_params[0] = afl_as ? afl_as : (u8*)"as";
as_params[argc] = 0; as_params[argc] = 0;
for (i = 1; i < argc - 1; i++) { for (i = 1; i < argc - 1; i++) {
if (!strcmp(argv[i], "--64")) use_64bit = 1; if (!strcmp(argv[i], "--64")) use_64bit = 1;
else if (!strcmp(argv[i], "--32")) use_64bit = 0; else if (!strcmp(argv[i], "--32")) use_64bit = 0;
#ifdef __APPLE__ #ifdef __APPLE__
/* The Apple case is a bit different... */ /* MacOS X 的情况有点不同... */
if (!strcmp(argv[i], "-arch") && i + 1 < argc) { if (!strcmp(argv[i], "-arch") && i + 1 < argc) {
if (!strcmp(argv[i + 1], "x86_64")) use_64bit = 1; if (!strcmp(argv[i + 1], "x86_64")) use_64bit = 1;
else if (!strcmp(argv[i + 1], "i386")) else if (!strcmp(argv[i + 1], "i386"))
FATAL("Sorry, 32-bit Apple platforms are not supported."); FATAL("Sorry, 32-bit Apple platforms are not supported.");
} }
/* Strip options that set the preference for a particular upstream /* 移除 Xcode 中设置特定上游汇编器的选项 */
assembler in Xcode. */
if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q"))) if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q")))
continue; continue;
#endif /* __APPLE__ */ #endif /* __APPLE__ */
as_params[as_par_cnt++] = argv[i]; as_params[as_par_cnt++] = argv[i];
} }
#ifdef __APPLE__ #ifdef __APPLE__
/* When calling clang as the upstream assembler, append -c -x assembler /* 当调用 clang 作为上游汇编器时,追加 -c -x assembler 选项并希望一切顺利。 */
and hope for the best. */
if (use_clang_as) { if (use_clang_as) {
as_params[as_par_cnt++] = "-c"; as_params[as_par_cnt++] = "-c";
as_params[as_par_cnt++] = "-x"; as_params[as_par_cnt++] = "-x";
as_params[as_par_cnt++] = "assembler"; as_params[as_par_cnt++] = "assembler";
} }
#endif /* __APPLE__ */ #endif /* __APPLE__ */
input_file = argv[argc - 1]; input_file = argv[argc - 1];
if (input_file[0] == '-') { if (input_file[0] == '-') {
if (!strcmp(input_file + 1, "-version")) { if (!strcmp(input_file + 1, "-version")) {
just_version = 1; just_version = 1;
modified_file = input_file; modified_file = input_file;
goto wrap_things_up; goto wrap_things_up;
} }
if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)"); if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)");
else input_file = NULL; else input_file = NULL;
} else { } else {
/* Check if this looks like a standard invocation as a part of an attempt /* 检查是否为标准调用,作为编译程序的一部分,而不是使用 gcc 对一个独立的 .s 文件进行编译。
to compile a program, rather than using gcc on an ad-hoc .s file in NSS */
a format we may not understand. This works around an issue compiling
NSS. */
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/var/tmp/", 9) &&
strncmp(input_file, "/tmp/", 5)) pass_thru = 1; strncmp(input_file, "/tmp/", 5)) pass_thru = 1;
} }
modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(), modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(),
(u32)time(NULL)); (u32)time(NULL));
wrap_things_up: wrap_things_up:
as_params[as_par_cnt++] = modified_file; as_params[as_par_cnt++] = modified_file;
as_params[as_par_cnt] = NULL; as_params[as_par_cnt] = NULL;
} }
/* Process input file, generate modified_file. Insert instrumentation in all /* 处理输入文件并生成 modified_file。在所有适当的位置插入插桩代码。 */
the appropriate places. */
static void add_instrumentation(void) { static void add_instrumentation(void) {
static u8 line[MAX_LINE]; static u8 line[MAX_LINE];
FILE* inf; FILE* inf;
FILE* outf; FILE* outf;
s32 outfd; s32 outfd;
u32 ins_lines = 0; u32 ins_lines = 0;
u8 instr_ok = 0, skip_csect = 0, skip_next_label = 0, u8 instr_ok = 0, skip_csect = 0, skip_next_label = 0,
skip_intel = 0, skip_app = 0, instrument_next = 0; skip_intel = 0, skip_app = 0, instrument_next = 0;
#ifdef __APPLE__ #ifdef __APPLE__
u8* colon_pos; u8* colon_pos;
#endif /* __APPLE__ */ #endif /* __APPLE__ */
if (input_file) { if (input_file) {
inf = fopen(input_file, "r"); inf = fopen(input_file, "r");
if (!inf) PFATAL("Unable to read '%s'", input_file); if (!inf) PFATAL("Unable to read '%s'", input_file);
} else inf = stdin; } else inf = stdin;
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);
if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file); if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file);
outf = fdopen(outfd, "w"); outf = fdopen(outfd, "w");
if (!outf) PFATAL("fdopen() failed"); if (!outf) PFATAL("fdopen() failed");
while (fgets(line, MAX_LINE, inf)) { while (fgets(line, MAX_LINE, inf)) {
/* In some cases, we want to defer writing the instrumentation trampoline /* 在某些情况下,我们希望在所有标签、宏、注释等之后再插入插桩跳板代码。
until after all the labels, macros, comments, etc. If we're in this */
mode, and if the line starts with a tab followed by a character, dump
the trampoline now. */
if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok && if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok &&
instrument_next && line[0] == '\t' && isalpha(line[1])) { instrument_next && line[0] == '\t' && isalpha(line[1])) {
fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32, fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
R(MAP_SIZE)); R(MAP_SIZE));
instrument_next = 0; instrument_next = 0;
ins_lines++; ins_lines++;
} }
/* Output the actual line, call it a day in pass-thru mode. */ /* 输出实际的行,在 pass-thru 模式下结束操作。 */
fputs(line, outf); fputs(line, outf);
if (pass_thru) continue; if (pass_thru) continue;
/* All right, this is where the actual fun begins. For one, we only want to /* 现在开始真正的插桩操作。首先,我们只希望插桩 .text 部分。
instrument the .text section. So, let's keep track of that in processed instr_ok */
files - and let's set instr_ok accordingly. */
if (line[0] == '\t' && line[1] == '.') { if (line[0] == '\t' && line[1] == '.') {
/* OpenBSD puts jump tables directly inline with the code, which is /* OpenBSD 在代码中直接放置跳转表,这稍微有点麻烦。
a bit annoying. They use a specific format of p2align directives 使 p2align 使 */
around them, so we use that as a signal. */
if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) && if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) &&
isdigit(line[10]) && line[11] == '\n') skip_next_label = 1; isdigit(line[10]) && line[11] == '\n') skip_next_label = 1;
if (!strncmp(line + 2, "text\n", 5) || if (!strncmp(line + 2, "text\n", 5) ||
!strncmp(line + 2, "section\t.text", 13) || !strncmp(line + 2, "section\t.text", 13) ||
!strncmp(line + 2, "section\t__TEXT,__text", 21) || !strncmp(line + 2, "section\t__TEXT,__text", 21) ||
@ -301,7 +286,7 @@ static void add_instrumentation(void) {
instr_ok = 1; instr_ok = 1;
continue; continue;
} }
if (!strncmp(line + 2, "section\t", 8) || if (!strncmp(line + 2, "section\t", 8) ||
!strncmp(line + 2, "section ", 8) || !strncmp(line + 2, "section ", 8) ||
!strncmp(line + 2, "bss\n", 4) || !strncmp(line + 2, "bss\n", 4) ||
@ -309,156 +294,136 @@ static void add_instrumentation(void) {
instr_ok = 0; instr_ok = 0;
continue; continue;
} }
} }
/* Detect off-flavor assembly (rare, happens in gdb). When this is /* 检测非常规汇编(罕见,例如在 gdb 中)。当遇到这种汇编时,我们设置 skip_csect
encountered, we set skip_csect until the opposite directive is */
seen, and we do not instrument. */
if (strstr(line, ".code")) { if (strstr(line, ".code")) {
if (strstr(line, ".code32")) skip_csect = use_64bit; if (strstr(line, ".code32")) skip_csect = use_64bit;
if (strstr(line, ".code64")) skip_csect = !use_64bit; if (strstr(line, ".code64")) skip_csect = !use_64bit;
} }
/* Detect syntax changes, as could happen with hand-written assembly. /* 检测并跳过手写汇编块__asm__同样不进行插桩。 */
Skip Intel blocks, resume instrumentation when back to AT&T. */
if (strstr(line, ".intel_syntax")) skip_intel = 1;
if (strstr(line, ".att_syntax")) skip_intel = 0;
/* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */
if (line[0] == '#' || line[1] == '#') { if (line[0] == '#' || line[1] == '#') {
if (strstr(line, "#APP")) skip_app = 1; if (strstr(line, "#APP")) skip_app = 1;
if (strstr(line, "#NO_APP")) skip_app = 0; if (strstr(line, "#NO_APP")) skip_app = 0;
} }
/* If we're in the right mood for instrumenting, check for function /* 如果我们处于插桩模式,检查函数名或条件标签。这里逻辑有些复杂,但基本目标是捕获:
names or conditional labels. This is a bit messy, but in essence,
we want to catch: ^main: -
^.L0: - GCC
^main: - function entry point (always instrumented) ^.LBB0_0: - clang clang
^.L0: - GCC branch label ^\tjnz foo -
^.LBB0_0: - clang branch label (but only in clang mode)
^\tjnz foo - conditional branches ...
...but not: ^# BB#0: - clang
^ # BB#0: -
^# BB#0: - clang comments ^.Ltmp0: - clang
^ # BB#0: - ditto ^.LC0 - GCC
^.Ltmp0: - clang non-branch labels ^.LBB0_0: - GCC
^.LC0 - GCC non-branch labels ^\tjmp foo -
^.LBB0_0: - ditto (when in GCC mode)
^\tjmp foo - non-conditional jumps MacOS X clang GCC 使
Additionally, clang and GCC on MacOS X follow a different convention
with no leading dots on labels, hence the weird maze of #ifdefs
later on.
*/ */
if (skip_intel || skip_app || skip_csect || !instr_ok || if (skip_intel || skip_app || skip_csect || !instr_ok ||
line[0] == '#' || line[0] == ' ') continue; line[0] == '#' || line[0] == ' ') continue;
/* Conditional branch instruction (jnz, etc). We append the instrumentation /* 条件分支指令jnz 等)。我们会在分支之后插入插桩(以插桩不执行路径),
right after the branch (to instrument the not-taken path) and at the */
branch destination label (handled later on). */
if (line[0] == '\t') { if (line[0] == '\t') {
if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) { if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) {
fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32, fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
R(MAP_SIZE)); R(MAP_SIZE));
ins_lines++; ins_lines++;
} }
continue; continue;
} }
/* Label of some sort. This may be a branch destination, but we need to /* 某类标签。这可能是分支目标,但我们需要小心处理不同的格式约定。 */
tread carefully and account for several different formatting
conventions. */
#ifdef __APPLE__ #ifdef __APPLE__
/* Apple: L<whatever><digit>: */ /* MacOS X: L<whatever><digit>: */
if ((colon_pos = strstr(line, ":"))) { if ((colon_pos = strstr(line, ":"))) {
if (line[0] == 'L' && isdigit(*(colon_pos - 1))) { if (line[0] == 'L' && isdigit(*(colon_pos - 1))) {
#else #else
/* Everybody else: .L<whatever>: */ /* 其他人:.L<whatever>: */
if (strstr(line, ":")) { if (strstr(line, ":")) {
if (line[0] == '.') { if (line[0] == '.') {
#endif /* __APPLE__ */ #endif /* __APPLE__ */
/* .L0: or LBB0_0: style jump destination */ /* .L0: 或 LBB0_0: 风格的分支目标 */
#ifdef __APPLE__ #ifdef __APPLE__
/* Apple: L<num> / LBB<num> */ /* MacOS X: L<num> / LBB<num> */
if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3))) if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3)))
&& R(100) < inst_ratio) { && R(100) < inst_ratio) {
#else #else
/* Apple: .L<num> / .LBB<num> */ /* MacOS X: .L<num> / .LBB<num> */
if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3))) if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3)))
&& R(100) < inst_ratio) { && R(100) < inst_ratio) {
#endif /* __APPLE__ */ #endif /* __APPLE__ */
/* An optimization is possible here by adding the code only if the /* 在仅需要在标签被引用时(非调用/跳转上下文)才添加代码的情况下可以进行优化。
label is mentioned in the code in contexts other than call / jmp. 使 stdin 10%
That said, this complicates the code by requiring two-pass
processing (messy with stdin), and results in a speed gain
typically under 10%, because compilers are generally pretty good 使 MacOS X .Lfunc_begin0 */
about not generating spurious intra-function jumps.
We use deferred output chiefly to avoid disrupting
.Lfunc_begin0-style exception handling calculations (a problem on
MacOS X). */
if (!skip_next_label) instrument_next = 1; else skip_next_label = 0; if (!skip_next_label) instrument_next = 1; else skip_next_label = 0;
} }
} else { } else {
/* Function label (always instrumented, deferred mode). */ /* 函数标签(总是插桩,延迟模式)。 */
instrument_next = 1; instrument_next = 1;
} }
} }
} }
if (ins_lines) if (ins_lines)
fputs(use_64bit ? main_payload_64 : main_payload_32, outf); fputs(use_64bit ? main_payload_64 : main_payload_32, outf);
if (input_file) fclose(inf); if (input_file) fclose(inf);
fclose(outf); fclose(outf);
if (!be_quiet) { if (!be_quiet) {
if (!ins_lines) WARNF("No instrumentation targets found%s.", if (!ins_lines) WARNF("No instrumentation targets found%s.",
pass_thru ? " (pass-thru mode)" : ""); pass_thru ? " (pass-thru mode)" : "");
else OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).", else OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).",
@ -466,92 +431,90 @@ static void add_instrumentation(void) {
getenv("AFL_HARDEN") ? "hardened" : getenv("AFL_HARDEN") ? "hardened" :
(sanitizer ? "ASAN/MSAN" : "non-hardened"), (sanitizer ? "ASAN/MSAN" : "non-hardened"),
inst_ratio); inst_ratio);
} }
} }
/* Main entry point */ /* 程序主入口点 */
int main(int argc, char** argv) { int main(int argc, char** argv) {
s32 pid; s32 pid;
u32 rand_seed; u32 rand_seed;
int status; int status;
u8* inst_ratio_str = getenv("AFL_INST_RATIO"); u8* inst_ratio_str = getenv("AFL_INST_RATIO");
struct timeval tv; struct timeval tv;
struct timezone tz; struct timezone tz;
clang_mode = !!getenv(CLANG_ENV_VAR); clang_mode = !!getenv(CLANG_ENV_VAR);
if (isatty(2) && !getenv("AFL_QUIET")) { if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(cCYA "afl-as " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-as " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
} else be_quiet = 1; } else be_quiet = 1;
if (argc < 2) { if (argc < 2) {
SAYF("\n" SAYF("\n"
"This is a helper application for afl-fuzz. It is a wrapper around GNU 'as',\n" "This is a helper application for afl-fuzz. It is a wrapper around GNU 'as',\n"
"executed by the toolchain whenever using afl-gcc or afl-clang. You probably\n" "executed by the toolchain whenever using afl-gcc or afl-clang. You probably\n"
"don't want to run this program directly.\n\n" "don't want to run this program directly.\n\n"
"Rarely, when dealing with extremely complex projects, it may be advisable to\n" "Rarely, when dealing with extremely complex projects, it may be advisable to\n"
"set AFL_INST_RATIO to a value less than 100 in order to reduce the odds of\n" "set AFL_INST_RATIO to a value less than 100 in order to reduce the odds of\n"
"instrumenting every discovered branch.\n\n"); "instrumenting every discovered branch.\n\n");
exit(1); exit(1);
} }
gettimeofday(&tv, &tz); gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
srandom(rand_seed); srandom(rand_seed);
edit_params(argc, argv); edit_params(argc, argv);
if (inst_ratio_str) { if (inst_ratio_str) {
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100)
FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)"); FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)");
} }
if (getenv(AS_LOOP_ENV_VAR)) if (getenv(AS_LOOP_ENV_VAR))
FATAL("Endless loop when calling 'as' (remove '.' from your PATH)"); FATAL("Endless loop when calling 'as' (remove '.' from your PATH)");
setenv(AS_LOOP_ENV_VAR, "1", 1); setenv(AS_LOOP_ENV_VAR, "1", 1);
/* When compiling with ASAN, we don't have a particularly elegant way to skip /* 使用 ASAN 时,我们没有特别优雅的方法来跳过 ASAN 特定的分支。
ASAN-specific branches. But we can probabilistically compensate for ... */
that... */
if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) { if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) {
sanitizer = 1; sanitizer = 1;
inst_ratio /= 3; inst_ratio /= 3;
} }
if (!just_version) add_instrumentation(); if (!just_version) add_instrumentation();
if (!(pid = fork())) { if (!(pid = fork())) {
execvp(as_params[0], (char**)as_params); execvp(as_params[0], (char**)as_params);
FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]); FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]);
} }
if (pid < 0) PFATAL("fork() failed"); if (pid < 0) PFATAL("fork() failed");
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file); if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file);
exit(WEXITSTATUS(status)); exit(WEXITSTATUS(status));
} }
Loading…
Cancel
Save