|
|
|
@ -452,344 +452,336 @@ static void detect_file_args(char** argv) {
|
|
|
|
|
argv[i] = n_arg;
|
|
|
|
|
*aa_loc = '@';
|
|
|
|
|
|
|
|
|
|
// 如果 at_file 不是绝对路径,则释放 aa_subst 内存
|
|
|
|
|
if (at_file[0] != '/') ck_free(aa_subst);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
i++; // 进入下一个参数
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(cwd); /* not tracked */
|
|
|
|
|
free(cwd); // 释放当前工作目录内存,但不进行追踪
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Show banner. */
|
|
|
|
|
|
|
|
|
|
// 显示工具的横幅信息
|
|
|
|
|
static void show_banner(void) {
|
|
|
|
|
|
|
|
|
|
// 输出工具名称以及作者信息
|
|
|
|
|
SAYF(cCYA "afl-showmap " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Display usage hints. */
|
|
|
|
|
|
|
|
|
|
// 显示用法提示信息
|
|
|
|
|
static void usage(u8* argv0) {
|
|
|
|
|
show_banner(); // 显示横幅信息
|
|
|
|
|
|
|
|
|
|
show_banner();
|
|
|
|
|
|
|
|
|
|
// 输出工具的用法信息和参数说明
|
|
|
|
|
SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
|
|
|
|
|
|
|
|
|
|
"Required parameters:\n\n"
|
|
|
|
|
|
|
|
|
|
" -o file - file to write the trace data to\n\n"
|
|
|
|
|
" -o file - file to write the trace data to\n\n" // 输出文件参数
|
|
|
|
|
|
|
|
|
|
// 输出工具的用法信息和参数说明
|
|
|
|
|
"Execution control settings:\n\n"
|
|
|
|
|
|
|
|
|
|
" -t msec - timeout for each run (none)\n"
|
|
|
|
|
" -m megs - memory limit for child process (%u MB)\n"
|
|
|
|
|
" -Q - use binary-only instrumentation (QEMU mode)\n\n"
|
|
|
|
|
" -t msec - timeout for each run (none)\n" // 设置每次执行的超时时间,单位为毫秒
|
|
|
|
|
" -m megs - memory limit for child process (%u MB)\n" // 设置子进程的内存限制,单位为MB
|
|
|
|
|
|
|
|
|
|
// 其他参数和设置选项的说明
|
|
|
|
|
"Other settings:\n\n"
|
|
|
|
|
|
|
|
|
|
" -q - sink program's output and don't show messages\n"
|
|
|
|
|
" -e - show edge coverage only, ignore hit counts\n"
|
|
|
|
|
" -c - allow core dumps\n"
|
|
|
|
|
" -V - show version number and exit\n\n"
|
|
|
|
|
" -q - sink program's output and don't show messages\n" // 隐藏程序输出,不显示信息
|
|
|
|
|
" -e - show edge coverage only, ignore hit counts\n" // 仅显示边缘覆盖,忽略命中计数
|
|
|
|
|
" -c - allow core dumps\n" // 允许生成核心转储
|
|
|
|
|
" -V - show version number and exit\n\n" // 显示版本号并退出
|
|
|
|
|
|
|
|
|
|
// 说明该工具的功能,并指向额外的帮助信息
|
|
|
|
|
"This tool displays raw tuple data captured by AFL instrumentation.\n"
|
|
|
|
|
"For additional help, consult %s/README.\n\n" cRST,
|
|
|
|
|
|
|
|
|
|
argv0, MEM_LIMIT, doc_path);
|
|
|
|
|
argv0, MEM_LIMIT, doc_path); // 输出用法信息,包括程序名、内存限制和文档路径
|
|
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
|
exit(1); // 退出程序,返回错误状态
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find binary. */
|
|
|
|
|
|
|
|
|
|
// 查找可执行二进制文件的函数
|
|
|
|
|
static void find_binary(u8* fname) {
|
|
|
|
|
u8* env_path = 0; // 环境变量路径
|
|
|
|
|
struct stat st; // 文件状态信息
|
|
|
|
|
|
|
|
|
|
u8* env_path = 0;
|
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
|
|
// 如果文件名包含 '/' 或者环境变量 PATH 不存在,直接使用提供的路径
|
|
|
|
|
if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
|
|
|
|
|
target_path = ck_strdup(fname); // 复制目标路径
|
|
|
|
|
|
|
|
|
|
target_path = ck_strdup(fname);
|
|
|
|
|
|
|
|
|
|
// 检查文件的状态,确认其存在且可执行
|
|
|
|
|
if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
|
|
|
|
|
!(st.st_mode & 0111) || st.st_size < 4)
|
|
|
|
|
FATAL("Program '%s' not found or not executable", fname);
|
|
|
|
|
|
|
|
|
|
FATAL("Program '%s' not found or not executable", fname); // 如果不可执行,则报错
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 逐个遍历 PATH 中的目录,并查找目标程序
|
|
|
|
|
while (env_path) {
|
|
|
|
|
u8 *cur_elem, *delim = strchr(env_path, ':'); // 分割当前路径元素
|
|
|
|
|
|
|
|
|
|
u8 *cur_elem, *delim = strchr(env_path, ':');
|
|
|
|
|
|
|
|
|
|
// 如果找到分隔符,则处理当前路径元素
|
|
|
|
|
if (delim) {
|
|
|
|
|
cur_elem = ck_alloc(delim - env_path + 1); // 分配内存
|
|
|
|
|
memcpy(cur_elem, env_path, delim - env_path); // 复制当前路径
|
|
|
|
|
delim++; // 指向下一个路径元素
|
|
|
|
|
} else
|
|
|
|
|
cur_elem = ck_strdup(env_path); // 没有分隔符,直接复制
|
|
|
|
|
|
|
|
|
|
cur_elem = ck_alloc(delim - env_path + 1);
|
|
|
|
|
memcpy(cur_elem, env_path, delim - env_path);
|
|
|
|
|
delim++;
|
|
|
|
|
|
|
|
|
|
} else cur_elem = ck_strdup(env_path);
|
|
|
|
|
|
|
|
|
|
env_path = delim;
|
|
|
|
|
env_path = delim; // 更新环境路径
|
|
|
|
|
|
|
|
|
|
// 构造目标路径
|
|
|
|
|
if (cur_elem[0])
|
|
|
|
|
target_path = alloc_printf("%s/%s", cur_elem, fname);
|
|
|
|
|
target_path = alloc_printf("%s/%s", cur_elem, fname); // 拼接路径
|
|
|
|
|
else
|
|
|
|
|
target_path = ck_strdup(fname);
|
|
|
|
|
target_path = ck_strdup(fname); // 若当前路径为空则直接使用文件名
|
|
|
|
|
|
|
|
|
|
ck_free(cur_elem);
|
|
|
|
|
ck_free(cur_elem); // 释放当前路径元素的内存
|
|
|
|
|
|
|
|
|
|
// 检查拼接后的目标路径是否有效
|
|
|
|
|
if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
|
|
|
|
|
(st.st_mode & 0111) && st.st_size >= 4) break;
|
|
|
|
|
|
|
|
|
|
ck_free(target_path);
|
|
|
|
|
target_path = 0;
|
|
|
|
|
(st.st_mode & 0111) && st.st_size >= 4) break; // 找到可执行文件,退出查找
|
|
|
|
|
|
|
|
|
|
ck_free(target_path); // 释放无效目标路径内存
|
|
|
|
|
target_path = 0; // 重新初始化目标路径
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果没有找到目标程序,则报错
|
|
|
|
|
if (!target_path) FATAL("Program '%s' not found or not executable", fname);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Fix up argv for QEMU. */
|
|
|
|
|
|
|
|
|
|
// 修复针对 QEMU 的 argv 参数
|
|
|
|
|
static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
|
|
|
|
|
|
|
|
|
|
char** new_argv = ck_alloc(sizeof(char*) * (argc + 4));
|
|
|
|
|
char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); // 分配新的参数数组内存
|
|
|
|
|
u8 *tmp, *cp, *rsl, *own_copy;
|
|
|
|
|
|
|
|
|
|
/* Workaround for a QEMU stability glitch. */
|
|
|
|
|
|
|
|
|
|
// 为了处理 QEMU 的稳定性问题,禁止链式调用
|
|
|
|
|
setenv("QEMU_LOG", "nochain", 1);
|
|
|
|
|
|
|
|
|
|
// 将原始参数复制到新的参数数组中
|
|
|
|
|
memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc);
|
|
|
|
|
|
|
|
|
|
new_argv[2] = target_path;
|
|
|
|
|
new_argv[1] = "--";
|
|
|
|
|
|
|
|
|
|
/* Now we need to actually find qemu for argv[0]. */
|
|
|
|
|
new_argv[2] = target_path; // 新参数的第三个元素为目标路径
|
|
|
|
|
new_argv[1] = "--"; // 添加分隔符 " -- " 以告诉 QEMU 参数的结束
|
|
|
|
|
|
|
|
|
|
// 查找 afl-qemu-trace 的路径,使用 AFL_PATH 环境变量
|
|
|
|
|
tmp = getenv("AFL_PATH");
|
|
|
|
|
|
|
|
|
|
if (tmp) {
|
|
|
|
|
cp = alloc_printf("%s/afl-qemu-trace", tmp); // 拼接 AFL_PATH
|
|
|
|
|
|
|
|
|
|
cp = alloc_printf("%s/afl-qemu-trace", tmp);
|
|
|
|
|
|
|
|
|
|
// 如果没有找到,则报错
|
|
|
|
|
if (access(cp, X_OK))
|
|
|
|
|
FATAL("Unable to find '%s'", tmp);
|
|
|
|
|
|
|
|
|
|
target_path = new_argv[0] = cp;
|
|
|
|
|
return new_argv;
|
|
|
|
|
|
|
|
|
|
target_path = new_argv[0] = cp; // 将找到的路径赋值给目标路径
|
|
|
|
|
return new_argv; // 返回新的参数数组
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 复制当前程序的路径以查找 afl-qemu-trace
|
|
|
|
|
own_copy = ck_strdup(own_loc);
|
|
|
|
|
rsl = strrchr(own_copy, '/');
|
|
|
|
|
rsl = strrchr(own_copy, '/'); // 找到最后一个 '/' 的位置
|
|
|
|
|
|
|
|
|
|
if (rsl) {
|
|
|
|
|
*rsl = 0; // 将最后一个 '/' 替换为终止符
|
|
|
|
|
|
|
|
|
|
*rsl = 0;
|
|
|
|
|
|
|
|
|
|
// 拼接 afl-qemu-trace 路径
|
|
|
|
|
cp = alloc_printf("%s/afl-qemu-trace", own_copy);
|
|
|
|
|
ck_free(own_copy);
|
|
|
|
|
ck_free(own_copy); // 释放复制的路径内存
|
|
|
|
|
|
|
|
|
|
// 检查拼接后的路径是否有效
|
|
|
|
|
if (!access(cp, X_OK)) {
|
|
|
|
|
|
|
|
|
|
target_path = new_argv[0] = cp;
|
|
|
|
|
return new_argv;
|
|
|
|
|
|
|
|
|
|
target_path = new_argv[0] = cp; // 更新目标路径
|
|
|
|
|
return new_argv; // 返回新的参数数组
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
ck_free(own_copy); // 如果没有找到 '/',则释放内存
|
|
|
|
|
|
|
|
|
|
} else ck_free(own_copy);
|
|
|
|
|
|
|
|
|
|
// 在默认的 BIN_PATH 查找 afl-qemu-trace
|
|
|
|
|
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
|
|
|
|
|
|
|
|
|
|
target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace";
|
|
|
|
|
return new_argv;
|
|
|
|
|
|
|
|
|
|
target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; // 设置目标路径
|
|
|
|
|
return new_argv; // 返回新的参数数组
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果以上步骤都未能找到 afl-qemu-trace,则报错
|
|
|
|
|
FATAL("Unable to find 'afl-qemu-trace'.");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Main entry point */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Main entry point
|
|
|
|
|
*/
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
|
|
|
|
|
|
s32 opt;
|
|
|
|
|
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0;
|
|
|
|
|
u32 tcnt;
|
|
|
|
|
char** use_argv;
|
|
|
|
|
s32 opt; // 选项变量
|
|
|
|
|
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0; // 标志变量
|
|
|
|
|
u32 tcnt; // 计数变量,用于记录捕获的元组数量
|
|
|
|
|
char** use_argv; // 用于存储最终的参数数组
|
|
|
|
|
|
|
|
|
|
// 检查文档路径是否存在,用于后续帮助信息
|
|
|
|
|
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
|
|
|
|
|
|
|
|
|
// 处理命令行参数
|
|
|
|
|
while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQbcV")) > 0)
|
|
|
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
|
|
|
|
|
|
case 'o':
|
|
|
|
|
|
|
|
|
|
if (out_file) FATAL("Multiple -o options not supported");
|
|
|
|
|
out_file = optarg;
|
|
|
|
|
// 处理输出文件参数
|
|
|
|
|
if (out_file) FATAL("Multiple -o options not supported"); // 防止重复设置
|
|
|
|
|
out_file = optarg; // 保存输出文件路径
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'm': {
|
|
|
|
|
u8 suffix = 'M'; // 默认单位为MB
|
|
|
|
|
|
|
|
|
|
u8 suffix = 'M';
|
|
|
|
|
|
|
|
|
|
if (mem_limit_given) FATAL("Multiple -m options not supported");
|
|
|
|
|
mem_limit_given = 1;
|
|
|
|
|
|
|
|
|
|
if (!strcmp(optarg, "none")) {
|
|
|
|
|
|
|
|
|
|
mem_limit = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
|
|
|
|
|
optarg[0] == '-') FATAL("Bad syntax used for -m");
|
|
|
|
|
|
|
|
|
|
switch (suffix) {
|
|
|
|
|
|
|
|
|
|
case 'T': mem_limit *= 1024 * 1024; break;
|
|
|
|
|
case 'G': mem_limit *= 1024; break;
|
|
|
|
|
case 'k': mem_limit /= 1024; break;
|
|
|
|
|
case 'M': break;
|
|
|
|
|
|
|
|
|
|
default: FATAL("Unsupported suffix or bad syntax for -m");
|
|
|
|
|
// 检查是否已经设置了内存限制
|
|
|
|
|
if (mem_limit_given) FATAL("Multiple -m options not supported");
|
|
|
|
|
mem_limit_given = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mem_limit < 5) FATAL("Dangerously low value of -m");
|
|
|
|
|
|
|
|
|
|
if (sizeof(rlim_t) == 4 && mem_limit > 2000)
|
|
|
|
|
FATAL("Value of -m out of range on 32-bit systems");
|
|
|
|
|
// 如果输入为 "none",则不设置内存限制
|
|
|
|
|
if (!strcmp(optarg, "none")) {
|
|
|
|
|
mem_limit = 0; // 设置内存限制为0
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析输入的内存限制
|
|
|
|
|
if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
|
|
|
|
|
optarg[0] == '-') FATAL("Bad syntax used for -m");
|
|
|
|
|
|
|
|
|
|
// 根据单位调整内存限制
|
|
|
|
|
switch (suffix) {
|
|
|
|
|
case 'T': mem_limit *= 1024 * 1024; break; // TB
|
|
|
|
|
case 'G': mem_limit *= 1024; break; // GB
|
|
|
|
|
case 'k': mem_limit /= 1024; break; // kB
|
|
|
|
|
case 'M': break; // MB
|
|
|
|
|
default: FATAL("Unsupported suffix or bad syntax for -m"); // 报错
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
// 设置的内存值不能低于阈值5
|
|
|
|
|
if (mem_limit < 5) FATAL("Dangerously low value of -m");
|
|
|
|
|
|
|
|
|
|
// 在32位系统中,内存限制不能超过2000MB
|
|
|
|
|
if (sizeof(rlim_t) == 4 && mem_limit > 2000)
|
|
|
|
|
FATAL("Value of -m out of range on 32-bit systems");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
|
|
|
|
|
|
// 处理超时时间参数
|
|
|
|
|
if (timeout_given) FATAL("Multiple -t options not supported");
|
|
|
|
|
timeout_given = 1;
|
|
|
|
|
|
|
|
|
|
// 如果不为 "none",则将输入解析为超时时间
|
|
|
|
|
if (strcmp(optarg, "none")) {
|
|
|
|
|
exec_tmout = atoi(optarg);
|
|
|
|
|
exec_tmout = atoi(optarg); // 将时间转换为整数
|
|
|
|
|
|
|
|
|
|
// 超时时间设置不能低于20毫秒
|
|
|
|
|
if (exec_tmout < 20 || optarg[0] == '-')
|
|
|
|
|
FATAL("Dangerously low value of -t");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'e':
|
|
|
|
|
|
|
|
|
|
if (edges_only) FATAL("Multiple -e options not supported");
|
|
|
|
|
edges_only = 1;
|
|
|
|
|
// 处理边缘覆盖参数
|
|
|
|
|
if (edges_only) FATAL("Multiple -e options not supported"); // 防止重复设置
|
|
|
|
|
edges_only = 1; // 设置为只显示边缘覆盖
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'q':
|
|
|
|
|
|
|
|
|
|
if (quiet_mode) FATAL("Multiple -q options not supported");
|
|
|
|
|
quiet_mode = 1;
|
|
|
|
|
// 处理安静模式参数
|
|
|
|
|
if (quiet_mode) FATAL("Multiple -q options not supported"); // 防止重复设置
|
|
|
|
|
quiet_mode = 1; // 启用安静模式
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'Z':
|
|
|
|
|
|
|
|
|
|
/* This is an undocumented option to write data in the syntax expected
|
|
|
|
|
by afl-cmin. Nobody else should have any use for this. */
|
|
|
|
|
|
|
|
|
|
// 处理 afl-cmin 特定功能参数
|
|
|
|
|
cmin_mode = 1;
|
|
|
|
|
quiet_mode = 1;
|
|
|
|
|
quiet_mode = 1; // 同时启用安静模式
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'A':
|
|
|
|
|
|
|
|
|
|
/* Another afl-cmin specific feature. */
|
|
|
|
|
at_file = optarg;
|
|
|
|
|
// 处理替代文件参数
|
|
|
|
|
at_file = optarg; // 保存替代文件名
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'Q':
|
|
|
|
|
// 处理 QEMU 特定功能参数
|
|
|
|
|
if (qemu_mode) FATAL("Multiple -Q options not supported"); // 防止重复设置
|
|
|
|
|
if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; // 若未设置内存限制,则使用 QEMU 的默认值
|
|
|
|
|
|
|
|
|
|
if (qemu_mode) FATAL("Multiple -Q options not supported");
|
|
|
|
|
if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
|
|
|
|
|
|
|
|
|
|
qemu_mode = 1;
|
|
|
|
|
qemu_mode = 1; // 启用 QEMU 模式
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
|
|
|
|
|
|
/* Secret undocumented mode. Writes output in raw binary format
|
|
|
|
|
similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */
|
|
|
|
|
|
|
|
|
|
binary_mode = 1;
|
|
|
|
|
// 处理原始二进制模式参数
|
|
|
|
|
binary_mode = 1; // 设置为原始二进制模式
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
|
|
|
|
|
|
if (keep_cores) FATAL("Multiple -c options not supported");
|
|
|
|
|
keep_cores = 1;
|
|
|
|
|
// 处理核心转储允许参数
|
|
|
|
|
if (keep_cores) FATAL("Multiple -c options not supported"); // 防止重复设置
|
|
|
|
|
keep_cores = 1; // 允许核心转储
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'V':
|
|
|
|
|
|
|
|
|
|
show_banner();
|
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
|
|
// 处理版本显示参数
|
|
|
|
|
show_banner(); // 显示工具的横幅信息
|
|
|
|
|
exit(0); // 退出程序
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
// 如果遇到未知参数则显示用法提示
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查命令行参数的完整性,如果缺少必要参数则显示用法信息
|
|
|
|
|
if (optind == argc || !out_file) usage(argv[0]);
|
|
|
|
|
|
|
|
|
|
// 设置共享内存和信号处理
|
|
|
|
|
setup_shm();
|
|
|
|
|
setup_signal_handlers();
|
|
|
|
|
|
|
|
|
|
// 设置环境变量
|
|
|
|
|
set_up_environment();
|
|
|
|
|
|
|
|
|
|
// 查找用户提供的二进制文件路径
|
|
|
|
|
find_binary(argv[optind]);
|
|
|
|
|
|
|
|
|
|
// 如果不是安静模式,则显示正在执行的程序信息
|
|
|
|
|
if (!quiet_mode) {
|
|
|
|
|
show_banner();
|
|
|
|
|
ACTF("Executing '%s'...\n", target_path);
|
|
|
|
|
show_banner(); // 显示横幅信息
|
|
|
|
|
ACTF("Executing '%s'...\n", target_path); // 显示正在执行的程序路径
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检测需要替换的文件参数
|
|
|
|
|
detect_file_args(argv + optind);
|
|
|
|
|
|
|
|
|
|
// 根据是否使用 QEMU 来准备参数数组
|
|
|
|
|
if (qemu_mode)
|
|
|
|
|
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
|
|
|
|
|
else
|
|
|
|
|
use_argv = argv + optind;
|
|
|
|
|
use_argv = argv + optind; // 如果不是 QEMU,使用原始参数数组
|
|
|
|
|
|
|
|
|
|
// 执行目标程序
|
|
|
|
|
run_target(use_argv);
|
|
|
|
|
|
|
|
|
|
// 写入执行结果
|
|
|
|
|
tcnt = write_results();
|
|
|
|
|
|
|
|
|
|
// 如果不是安静模式,则输出结果提示信息
|
|
|
|
|
if (!quiet_mode) {
|
|
|
|
|
|
|
|
|
|
if (!tcnt) FATAL("No instrumentation detected" cRST);
|
|
|
|
|
OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file);
|
|
|
|
|
|
|
|
|
|
if (!tcnt) FATAL("No instrumentation detected" cRST); // 如果没有捕获到元组数据,则报错
|
|
|
|
|
OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file); // 输出捕获到的元组数量
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 退出程序,返回状态值,状态值根据是否崩溃和超时进行设置
|
|
|
|
|
exit(child_crashed * 2 + child_timed_out);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|