OLD | NEW |
(Empty) | |
| 1 /* |
| 2 american fuzzy lop - injectable parts |
| 3 ------------------------------------- |
| 4 |
| 5 Written and maintained by Michal Zalewski <lcamtuf@google.com> |
| 6 |
| 7 Forkserver design by Jann Horn <jannhorn@googlemail.com> |
| 8 |
| 9 Copyright 2013, 2014, 2015 Google Inc. All rights reserved. |
| 10 |
| 11 Licensed under the Apache License, Version 2.0 (the "License"); |
| 12 you may not use this file except in compliance with the License. |
| 13 You may obtain a copy of the License at: |
| 14 |
| 15 http://www.apache.org/licenses/LICENSE-2.0 |
| 16 |
| 17 This file houses the assembly-level instrumentation injected into fuzzed |
| 18 programs. The instrumentation stores XORed pairs of data: identifiers of the |
| 19 currently executing branch and the one that executed immediately before. |
| 20 |
| 21 TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++ |
| 22 |
| 23 The code is designed for 32-bit and 64-bit x86 systems. Both modes should |
| 24 work everywhere except for Apple systems. Apple does relocations differently |
| 25 from everybody else, so since their OSes have been 64-bit for a longer while, |
| 26 I didn't go through the mental effort of porting the 32-bit code. |
| 27 |
| 28 In principle, similar code should be easy to inject into any well-behaved |
| 29 binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural |
| 30 targets for instrumentation, and should offer comparable probe density. |
| 31 |
| 32 */ |
| 33 |
| 34 #ifndef _HAVE_AFL_AS_H |
| 35 #define _HAVE_AFL_AS_H |
| 36 |
| 37 #include "config.h" |
| 38 #include "types.h" |
| 39 |
| 40 /* |
| 41 ------------------ |
| 42 Performances notes |
| 43 ------------------ |
| 44 |
| 45 Contributions to make this code faster are appreciated! Here are some |
| 46 rough notes that may help with the task: |
| 47 |
| 48 - Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are |
| 49 really worth optimizing; the setup / fork server stuff matters a lot less |
| 50 and should be mostly just kept readable. |
| 51 |
| 52 - We're aiming for modern CPUs with out-of-order execution and large |
| 53 pipelines; the code is mostly follows intuitive, human-readable |
| 54 instruction ordering, because "textbook" manual reorderings make no |
| 55 substantial difference. |
| 56 |
| 57 - Interestingly, instrumented execution isn't a lot faster if we store a |
| 58 variable pointer to the setup, log, or return routine and then do a reg |
| 59 call from within trampoline_fmt. It does speed up non-instrumented |
| 60 execution quite a bit, though, since that path just becomes |
| 61 push-call-ret-pop. |
| 62 |
| 63 - There is also not a whole lot to be gained by doing SHM attach at a |
| 64 fixed address instead of retrieving __afl_area_ptr. Although it allows us |
| 65 to have a shorter log routine inserted for conditional jumps and jump |
| 66 labels (for a ~10% perf gain), there is a risk of bumping into other |
| 67 allocations created by the program or by tools such as ASAN. |
| 68 |
| 69 - popf is *awfully* slow, which is why we're doing the lahf / sahf + |
| 70 overflow test trick. Unfortunately, this forces us to taint eax / rax, but |
| 71 this dependency on a commonly-used register still beats the alternative of |
| 72 using pushf / popf. |
| 73 |
| 74 One possible optimization is to avoid touching flags by using a circular |
| 75 buffer that stores just a sequence of current locations, with the XOR stuff |
| 76 happening offline. Alas, this doesn't seem to have a huge impact: |
| 77 |
| 78 https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ |
| 79 |
| 80 - Preforking one child a bit sooner, and then waiting for the "go" command |
| 81 from within the child, doesn't offer major performance gains; fork() seems |
| 82 to be relatively inexpensive these days. Preforking multiple children does |
| 83 help, but badly breaks the "~1 core per fuzzer" design, making it harder to |
| 84 scale up. Maybe there is some middle ground. |
| 85 |
| 86 Perhaps of note: in the 64-bit version for all platforms except for Apple, |
| 87 the instrumentation is done slightly differently than on 32-bit, with |
| 88 __afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm), |
| 89 rather than global (.comm). This is to avoid GOTRELPC lookups in the critical |
| 90 code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to |
| 91 work; simple relocations between .bss and .text won't work on most 64-bit |
| 92 platforms in such a case. |
| 93 |
| 94 (Fun fact: on Apple systems, .lcomm can segfault the linker.) |
| 95 |
| 96 The side effect is that state transitions are measured in a somewhat |
| 97 different way, with previous tuple being recorded separately within the scope |
| 98 of every .c file. This should have no impact in any practical sense. |
| 99 |
| 100 Another side effect of this design is that getenv() will be called once per |
| 101 every .o file when running in non-instrumented mode; an since getenv() tends |
| 102 to be optimized in funny ways, we need to be very careful to save every |
| 103 oddball register it may touch. |
| 104 |
| 105 */ |
| 106 |
| 107 static const u8* trampoline_fmt_32 = |
| 108 |
| 109 "\n" |
| 110 "/* --- AFL TRAMPOLINE (32-BIT) --- */\n" |
| 111 "\n" |
| 112 ".align 4\n" |
| 113 "\n" |
| 114 "leal -16(%%esp), %%esp\n" |
| 115 "movl %%edi, 0(%%esp)\n" |
| 116 "movl %%edx, 4(%%esp)\n" |
| 117 "movl %%ecx, 8(%%esp)\n" |
| 118 "movl %%eax, 12(%%esp)\n" |
| 119 "movl $0x%08x, %%ecx\n" |
| 120 "call __afl_maybe_log\n" |
| 121 "movl 12(%%esp), %%eax\n" |
| 122 "movl 8(%%esp), %%ecx\n" |
| 123 "movl 4(%%esp), %%edx\n" |
| 124 "movl 0(%%esp), %%edi\n" |
| 125 "leal 16(%%esp), %%esp\n" |
| 126 "\n" |
| 127 "/* --- END --- */\n" |
| 128 "\n"; |
| 129 |
| 130 static const u8* trampoline_fmt_64 = |
| 131 |
| 132 "\n" |
| 133 "/* --- AFL TRAMPOLINE (64-BIT) --- */\n" |
| 134 "\n" |
| 135 ".align 4\n" |
| 136 "\n" |
| 137 "leaq -(128+24)(%%rsp), %%rsp\n" |
| 138 "movq %%rdx, 0(%%rsp)\n" |
| 139 "movq %%rcx, 8(%%rsp)\n" |
| 140 "movq %%rax, 16(%%rsp)\n" |
| 141 "movq $0x%08x, %%rcx\n" |
| 142 "call __afl_maybe_log\n" |
| 143 "movq 16(%%rsp), %%rax\n" |
| 144 "movq 8(%%rsp), %%rcx\n" |
| 145 "movq 0(%%rsp), %%rdx\n" |
| 146 "leaq (128+24)(%%rsp), %%rsp\n" |
| 147 "\n" |
| 148 "/* --- END --- */\n" |
| 149 "\n"; |
| 150 |
| 151 static const u8* main_payload_32 = |
| 152 |
| 153 "\n" |
| 154 "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n" |
| 155 "\n" |
| 156 ".text\n" |
| 157 ".att_syntax\n" |
| 158 ".code32\n" |
| 159 ".align 8\n" |
| 160 "\n" |
| 161 |
| 162 "__afl_maybe_log:\n" |
| 163 "\n" |
| 164 " lahf\n" |
| 165 " seto %al\n" |
| 166 "\n" |
| 167 " /* Check if SHM region is already mapped. */\n" |
| 168 "\n" |
| 169 " movl __afl_area_ptr, %edx\n" |
| 170 " testl %edx, %edx\n" |
| 171 " je __afl_setup\n" |
| 172 "\n" |
| 173 "__afl_store:\n" |
| 174 "\n" |
| 175 " /* Calculate and store hit for the code location specified in ecx. There\n" |
| 176 " is a double-XOR way of doing this without tainting another register,\n" |
| 177 " and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n" |
| 178 "\n" |
| 179 #ifndef COVERAGE_ONLY |
| 180 " movl __afl_prev_loc, %edi\n" |
| 181 " xorl %ecx, %edi\n" |
| 182 " shrl $1, %ecx\n" |
| 183 " movl %ecx, __afl_prev_loc\n" |
| 184 #endif /* !COVERAGE_ONLY */ |
| 185 "\n" |
| 186 #ifdef SKIP_COUNTS |
| 187 " orb $1, (%edx, %edi, 1)\n" |
| 188 #else |
| 189 " incb (%edx, %edi, 1)\n" |
| 190 #endif /* ^SKIP_COUNTS */ |
| 191 "\n" |
| 192 "__afl_return:\n" |
| 193 "\n" |
| 194 " addb $127, %al\n" |
| 195 " sahf\n" |
| 196 " ret\n" |
| 197 "\n" |
| 198 ".align 8\n" |
| 199 "\n" |
| 200 "__afl_setup:\n" |
| 201 "\n" |
| 202 " /* Do not retry setup if we had previous failures. */\n" |
| 203 "\n" |
| 204 " cmpb $0, __afl_setup_failure\n" |
| 205 " jne __afl_return\n" |
| 206 "\n" |
| 207 " /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n" |
| 208 " We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n" |
| 209 " will notice this early in the game. */\n" |
| 210 "\n" |
| 211 " pushl %eax\n" |
| 212 " pushl %ecx\n" |
| 213 "\n" |
| 214 " pushl $.AFL_SHM_ENV\n" |
| 215 " call getenv\n" |
| 216 " addl $4, %esp\n" |
| 217 "\n" |
| 218 " testl %eax, %eax\n" |
| 219 " je __afl_setup_abort\n" |
| 220 "\n" |
| 221 " pushl %eax\n" |
| 222 " call atoi\n" |
| 223 " addl $4, %esp\n" |
| 224 "\n" |
| 225 " pushl $0 /* shmat flags */\n" |
| 226 " pushl $0 /* requested addr */\n" |
| 227 " pushl %eax /* SHM ID */\n" |
| 228 " call shmat\n" |
| 229 " addl $12, %esp\n" |
| 230 "\n" |
| 231 " cmpl $-1, %eax\n" |
| 232 " je __afl_setup_abort\n" |
| 233 "\n" |
| 234 " /* Store the address of the SHM region. */\n" |
| 235 "\n" |
| 236 " movl %eax, __afl_area_ptr\n" |
| 237 " movl %eax, %edx\n" |
| 238 "\n" |
| 239 " popl %ecx\n" |
| 240 " popl %eax\n" |
| 241 "\n" |
| 242 "__afl_forkserver:\n" |
| 243 "\n" |
| 244 " /* Enter the fork server mode to avoid the overhead of execve() calls. */\n
" |
| 245 "\n" |
| 246 " pushl %eax\n" |
| 247 " pushl %ecx\n" |
| 248 " pushl %edx\n" |
| 249 "\n" |
| 250 " /* Phone home and tell the parent that we're OK. (Note that signals with\n" |
| 251 " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" |
| 252 " closed because we were execve()d from an instrumented binary, or because
\n" |
| 253 " the parent doesn't want to use the fork server. */\n" |
| 254 "\n" |
| 255 " pushl $4 /* length */\n" |
| 256 " pushl $__afl_temp /* data */\n" |
| 257 " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" |
| 258 " call write\n" |
| 259 " addl $12, %esp\n" |
| 260 "\n" |
| 261 " cmpl $4, %eax\n" |
| 262 " jne __afl_fork_resume\n" |
| 263 "\n" |
| 264 "__afl_fork_wait_loop:\n" |
| 265 "\n" |
| 266 " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" |
| 267 "\n" |
| 268 " pushl $4 /* length */\n" |
| 269 " pushl $__afl_temp /* data */\n" |
| 270 " pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n" |
| 271 " call read\n" |
| 272 " addl $12, %esp\n" |
| 273 "\n" |
| 274 " cmpl $4, %eax\n" |
| 275 " jne __afl_die\n" |
| 276 "\n" |
| 277 " /* Once woken up, create a clone of our process. This is an excellent use\n
" |
| 278 " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" |
| 279 " caches getpid() results and offers no way to update the value, breaking\
n" |
| 280 " abort(), raise(), and a bunch of other things :-( */\n" |
| 281 "\n" |
| 282 " call fork\n" |
| 283 "\n" |
| 284 " cmpl $0, %eax\n" |
| 285 " jl __afl_die\n" |
| 286 " je __afl_fork_resume\n" |
| 287 "\n" |
| 288 " /* In parent process: write PID to pipe, then wait for child. */\n" |
| 289 "\n" |
| 290 " movl %eax, __afl_fork_pid\n" |
| 291 "\n" |
| 292 " pushl $4 /* length */\n" |
| 293 " pushl $__afl_fork_pid /* data */\n" |
| 294 " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" |
| 295 " call write\n" |
| 296 " addl $12, %esp\n" |
| 297 "\n" |
| 298 " pushl $0 /* no flags */\n" |
| 299 " pushl $__afl_temp /* status */\n" |
| 300 " pushl __afl_fork_pid /* PID */\n" |
| 301 " call waitpid\n" |
| 302 " addl $12, %esp\n" |
| 303 "\n" |
| 304 " cmpl $0, %eax\n" |
| 305 " jle __afl_die\n" |
| 306 "\n" |
| 307 " /* Relay wait status to pipe, then loop back. */\n" |
| 308 "\n" |
| 309 " pushl $4 /* length */\n" |
| 310 " pushl $__afl_temp /* data */\n" |
| 311 " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" |
| 312 " call write\n" |
| 313 " addl $12, %esp\n" |
| 314 "\n" |
| 315 " jmp __afl_fork_wait_loop\n" |
| 316 "\n" |
| 317 "__afl_fork_resume:\n" |
| 318 "\n" |
| 319 " /* In child process: close fds, resume execution. */\n" |
| 320 "\n" |
| 321 " pushl $" STRINGIFY(FORKSRV_FD) "\n" |
| 322 " call close\n" |
| 323 "\n" |
| 324 " pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n" |
| 325 " call close\n" |
| 326 "\n" |
| 327 " addl $8, %esp\n" |
| 328 "\n" |
| 329 " popl %edx\n" |
| 330 " popl %ecx\n" |
| 331 " popl %eax\n" |
| 332 " jmp __afl_store\n" |
| 333 "\n" |
| 334 "__afl_die:\n" |
| 335 "\n" |
| 336 " xorl %eax, %eax\n" |
| 337 " call _exit\n" |
| 338 "\n" |
| 339 "__afl_setup_abort:\n" |
| 340 "\n" |
| 341 " /* Record setup failure so that we don't keep calling\n" |
| 342 " shmget() / shmat() over and over again. */\n" |
| 343 "\n" |
| 344 " incb __afl_setup_failure\n" |
| 345 " popl %ecx\n" |
| 346 " popl %eax\n" |
| 347 " jmp __afl_return\n" |
| 348 "\n" |
| 349 ".AFL_VARS:\n" |
| 350 "\n" |
| 351 " .comm __afl_area_ptr, 4, 32\n" |
| 352 " .comm __afl_setup_failure, 1, 32\n" |
| 353 #ifndef COVERAGE_ONLY |
| 354 " .comm __afl_prev_loc, 4, 32\n" |
| 355 #endif /* !COVERAGE_ONLY */ |
| 356 " .comm __afl_fork_pid, 4, 32\n" |
| 357 " .comm __afl_temp, 4, 32\n" |
| 358 "\n" |
| 359 ".AFL_SHM_ENV:\n" |
| 360 " .asciz \"" SHM_ENV_VAR "\"\n" |
| 361 "\n" |
| 362 "/* --- END --- */\n" |
| 363 "\n"; |
| 364 |
| 365 /* The OpenBSD hack is due to lahf and sahf not being recognized by some |
| 366 versions of binutils: http://marc.info/?l=openbsd-cvs&m=141636589924400 |
| 367 |
| 368 The Apple code is a bit different when calling libc functions because |
| 369 they are doing relocations differently from everybody else. We also need |
| 370 to work around the crash issue with .lcomm and the fact that they don't |
| 371 recognize .string. */ |
| 372 |
| 373 #ifdef __APPLE__ |
| 374 # define CALL_L64(str) "call _" str "\n" |
| 375 #else |
| 376 # define CALL_L64(str) "call " str "@PLT\n" |
| 377 #endif /* ^__APPLE__ */ |
| 378 |
| 379 static const u8* main_payload_64 = |
| 380 |
| 381 "\n" |
| 382 "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n" |
| 383 "\n" |
| 384 ".text\n" |
| 385 ".att_syntax\n" |
| 386 ".code64\n" |
| 387 ".align 8\n" |
| 388 "\n" |
| 389 "__afl_maybe_log:\n" |
| 390 "\n" |
| 391 #if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) |
| 392 " .byte 0x9f /* lahf */\n" |
| 393 #else |
| 394 " lahf\n" |
| 395 #endif /* ^__OpenBSD__, etc */ |
| 396 " seto %al\n" |
| 397 "\n" |
| 398 " /* Check if SHM region is already mapped. */\n" |
| 399 "\n" |
| 400 " movq __afl_area_ptr(%rip), %rdx\n" |
| 401 " testq %rdx, %rdx\n" |
| 402 " je __afl_setup\n" |
| 403 "\n" |
| 404 "__afl_store:\n" |
| 405 "\n" |
| 406 " /* Calculate and store hit for the code location specified in rcx. */\n" |
| 407 "\n" |
| 408 #ifndef COVERAGE_ONLY |
| 409 " xorq __afl_prev_loc(%rip), %rcx\n" |
| 410 " xorq %rcx, __afl_prev_loc(%rip)\n" |
| 411 " shrq $1, __afl_prev_loc(%rip)\n" |
| 412 #endif /* ^!COVERAGE_ONLY */ |
| 413 "\n" |
| 414 #ifdef SKIP_COUNTS |
| 415 " orb $1, (%rdx, %rcx, 1)\n" |
| 416 #else |
| 417 " incb (%rdx, %rcx, 1)\n" |
| 418 #endif /* ^SKIP_COUNTS */ |
| 419 "\n" |
| 420 "__afl_return:\n" |
| 421 "\n" |
| 422 " addb $127, %al\n" |
| 423 #if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) |
| 424 " .byte 0x9e /* sahf */\n" |
| 425 #else |
| 426 " sahf\n" |
| 427 #endif /* ^__OpenBSD__, etc */ |
| 428 " ret\n" |
| 429 "\n" |
| 430 ".align 8\n" |
| 431 "\n" |
| 432 "__afl_setup:\n" |
| 433 "\n" |
| 434 " /* Do not retry setup if we had previous failures. */\n" |
| 435 "\n" |
| 436 " cmpb $0, __afl_setup_failure(%rip)\n" |
| 437 " jne __afl_return\n" |
| 438 "\n" |
| 439 " /* Check out if we have a global pointer on file. */\n" |
| 440 "\n" |
| 441 #ifndef __APPLE__ |
| 442 " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" |
| 443 " movq (%rdx), %rdx\n" |
| 444 #else |
| 445 " movq __afl_global_area_ptr(%rip), %rdx\n" |
| 446 #endif /* !^__APPLE__ */ |
| 447 " testq %rdx, %rdx\n" |
| 448 " je __afl_setup_first\n" |
| 449 "\n" |
| 450 " movq %rdx, __afl_area_ptr(%rip)\n" |
| 451 " jmp __afl_store\n" |
| 452 "\n" |
| 453 "__afl_setup_first:\n" |
| 454 "\n" |
| 455 " /* Save everything that is not yet saved and that may be touched by\n" |
| 456 " getenv() and several other libcalls we'll be relying on. */\n" |
| 457 "\n" |
| 458 " leaq -352(%rsp), %rsp\n" |
| 459 "\n" |
| 460 " movq %rax, 0(%rsp)\n" |
| 461 " movq %rcx, 8(%rsp)\n" |
| 462 " movq %rdi, 16(%rsp)\n" |
| 463 " movq %rsi, 32(%rsp)\n" |
| 464 " movq %r8, 40(%rsp)\n" |
| 465 " movq %r9, 48(%rsp)\n" |
| 466 " movq %r10, 56(%rsp)\n" |
| 467 " movq %r11, 64(%rsp)\n" |
| 468 "\n" |
| 469 " movq %xmm0, 96(%rsp)\n" |
| 470 " movq %xmm1, 112(%rsp)\n" |
| 471 " movq %xmm2, 128(%rsp)\n" |
| 472 " movq %xmm3, 144(%rsp)\n" |
| 473 " movq %xmm4, 160(%rsp)\n" |
| 474 " movq %xmm5, 176(%rsp)\n" |
| 475 " movq %xmm6, 192(%rsp)\n" |
| 476 " movq %xmm7, 208(%rsp)\n" |
| 477 " movq %xmm8, 224(%rsp)\n" |
| 478 " movq %xmm9, 240(%rsp)\n" |
| 479 " movq %xmm10, 256(%rsp)\n" |
| 480 " movq %xmm11, 272(%rsp)\n" |
| 481 " movq %xmm12, 288(%rsp)\n" |
| 482 " movq %xmm13, 304(%rsp)\n" |
| 483 " movq %xmm14, 320(%rsp)\n" |
| 484 " movq %xmm15, 336(%rsp)\n" |
| 485 "\n" |
| 486 " /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n" |
| 487 "\n" |
| 488 " /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n" |
| 489 " original stack ptr in the callee-saved r12. */\n" |
| 490 "\n" |
| 491 " pushq %r12\n" |
| 492 " movq %rsp, %r12\n" |
| 493 " subq $16, %rsp\n" |
| 494 " andq $0xfffffffffffffff0, %rsp\n" |
| 495 "\n" |
| 496 " leaq .AFL_SHM_ENV(%rip), %rdi\n" |
| 497 CALL_L64("getenv") |
| 498 "\n" |
| 499 " testq %rax, %rax\n" |
| 500 " je __afl_setup_abort\n" |
| 501 "\n" |
| 502 " movq %rax, %rdi\n" |
| 503 CALL_L64("atoi") |
| 504 "\n" |
| 505 " xorq %rdx, %rdx /* shmat flags */\n" |
| 506 " xorq %rsi, %rsi /* requested addr */\n" |
| 507 " movq %rax, %rdi /* SHM ID */\n" |
| 508 CALL_L64("shmat") |
| 509 "\n" |
| 510 " cmpq $-1, %rax\n" |
| 511 " je __afl_setup_abort\n" |
| 512 "\n" |
| 513 " /* Store the address of the SHM region. */\n" |
| 514 "\n" |
| 515 " movq %rax, %rdx\n" |
| 516 " movq %rax, __afl_area_ptr(%rip)\n" |
| 517 "\n" |
| 518 #ifdef __APPLE__ |
| 519 " movq %rax, __afl_global_area_ptr(%rip)\n" |
| 520 #else |
| 521 " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" |
| 522 " movq %rax, (%rdx)\n" |
| 523 #endif /* ^__APPLE__ */ |
| 524 " movq %rax, %rdx\n" |
| 525 "\n" |
| 526 "__afl_forkserver:\n" |
| 527 "\n" |
| 528 " /* Enter the fork server mode to avoid the overhead of execve() calls. We\n
" |
| 529 " push rdx (area ptr) twice to keep stack alignment neat. */\n" |
| 530 "\n" |
| 531 " pushq %rdx\n" |
| 532 " pushq %rdx\n" |
| 533 "\n" |
| 534 " /* Phone home and tell the parent that we're OK. (Note that signals with\n" |
| 535 " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" |
| 536 " closed because we were execve()d from an instrumented binary, or because
\n" |
| 537 " the parent doesn't want to use the fork server. */\n" |
| 538 "\n" |
| 539 " movq $4, %rdx /* length */\n" |
| 540 " leaq __afl_temp(%rip), %rsi /* data */\n" |
| 541 " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" |
| 542 CALL_L64("write") |
| 543 "\n" |
| 544 " cmpq $4, %rax\n" |
| 545 " jne __afl_fork_resume\n" |
| 546 "\n" |
| 547 "__afl_fork_wait_loop:\n" |
| 548 "\n" |
| 549 " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" |
| 550 "\n" |
| 551 " movq $4, %rdx /* length */\n" |
| 552 " leaq __afl_temp(%rip), %rsi /* data */\n" |
| 553 " movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n" |
| 554 CALL_L64("read") |
| 555 " cmpq $4, %rax\n" |
| 556 " jne __afl_die\n" |
| 557 "\n" |
| 558 " /* Once woken up, create a clone of our process. This is an excellent use\n
" |
| 559 " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" |
| 560 " caches getpid() results and offers no way to update the value, breaking\
n" |
| 561 " abort(), raise(), and a bunch of other things :-( */\n" |
| 562 "\n" |
| 563 CALL_L64("fork") |
| 564 " cmpq $0, %rax\n" |
| 565 " jl __afl_die\n" |
| 566 " je __afl_fork_resume\n" |
| 567 "\n" |
| 568 " /* In parent process: write PID to pipe, then wait for child. */\n" |
| 569 "\n" |
| 570 " movl %eax, __afl_fork_pid(%rip)\n" |
| 571 "\n" |
| 572 " movq $4, %rdx /* length */\n" |
| 573 " leaq __afl_fork_pid(%rip), %rsi /* data */\n" |
| 574 " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" |
| 575 CALL_L64("write") |
| 576 "\n" |
| 577 " movq $0, %rdx /* no flags */\n" |
| 578 " leaq __afl_temp(%rip), %rsi /* status */\n" |
| 579 " movq __afl_fork_pid(%rip), %rdi /* PID */\n" |
| 580 CALL_L64("waitpid") |
| 581 " cmpq $0, %rax\n" |
| 582 " jle __afl_die\n" |
| 583 "\n" |
| 584 " /* Relay wait status to pipe, then loop back. */\n" |
| 585 "\n" |
| 586 " movq $4, %rdx /* length */\n" |
| 587 " leaq __afl_temp(%rip), %rsi /* data */\n" |
| 588 " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" |
| 589 CALL_L64("write") |
| 590 "\n" |
| 591 " jmp __afl_fork_wait_loop\n" |
| 592 "\n" |
| 593 "__afl_fork_resume:\n" |
| 594 "\n" |
| 595 " /* In child process: close fds, resume execution. */\n" |
| 596 "\n" |
| 597 " movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n" |
| 598 CALL_L64("close") |
| 599 "\n" |
| 600 " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n" |
| 601 CALL_L64("close") |
| 602 "\n" |
| 603 " popq %rdx\n" |
| 604 " popq %rdx\n" |
| 605 "\n" |
| 606 " movq %r12, %rsp\n" |
| 607 " popq %r12\n" |
| 608 "\n" |
| 609 " movq 0(%rsp), %rax\n" |
| 610 " movq 8(%rsp), %rcx\n" |
| 611 " movq 16(%rsp), %rdi\n" |
| 612 " movq 32(%rsp), %rsi\n" |
| 613 " movq 40(%rsp), %r8\n" |
| 614 " movq 48(%rsp), %r9\n" |
| 615 " movq 56(%rsp), %r10\n" |
| 616 " movq 64(%rsp), %r11\n" |
| 617 "\n" |
| 618 " movq 96(%rsp), %xmm0\n" |
| 619 " movq 112(%rsp), %xmm1\n" |
| 620 " movq 128(%rsp), %xmm2\n" |
| 621 " movq 144(%rsp), %xmm3\n" |
| 622 " movq 160(%rsp), %xmm4\n" |
| 623 " movq 176(%rsp), %xmm5\n" |
| 624 " movq 192(%rsp), %xmm6\n" |
| 625 " movq 208(%rsp), %xmm7\n" |
| 626 " movq 224(%rsp), %xmm8\n" |
| 627 " movq 240(%rsp), %xmm9\n" |
| 628 " movq 256(%rsp), %xmm10\n" |
| 629 " movq 272(%rsp), %xmm11\n" |
| 630 " movq 288(%rsp), %xmm12\n" |
| 631 " movq 304(%rsp), %xmm13\n" |
| 632 " movq 320(%rsp), %xmm14\n" |
| 633 " movq 336(%rsp), %xmm15\n" |
| 634 "\n" |
| 635 " leaq 352(%rsp), %rsp\n" |
| 636 "\n" |
| 637 " jmp __afl_store\n" |
| 638 "\n" |
| 639 "__afl_die:\n" |
| 640 "\n" |
| 641 " xorq %rax, %rax\n" |
| 642 CALL_L64("_exit") |
| 643 "\n" |
| 644 "__afl_setup_abort:\n" |
| 645 "\n" |
| 646 " /* Record setup failure so that we don't keep calling\n" |
| 647 " shmget() / shmat() over and over again. */\n" |
| 648 "\n" |
| 649 " incb __afl_setup_failure(%rip)\n" |
| 650 "\n" |
| 651 " movq %r12, %rsp\n" |
| 652 " popq %r12\n" |
| 653 "\n" |
| 654 " movq 0(%rsp), %rax\n" |
| 655 " movq 8(%rsp), %rcx\n" |
| 656 " movq 16(%rsp), %rdi\n" |
| 657 " movq 32(%rsp), %rsi\n" |
| 658 " movq 40(%rsp), %r8\n" |
| 659 " movq 48(%rsp), %r9\n" |
| 660 " movq 56(%rsp), %r10\n" |
| 661 " movq 64(%rsp), %r11\n" |
| 662 "\n" |
| 663 " movq 96(%rsp), %xmm0\n" |
| 664 " movq 112(%rsp), %xmm1\n" |
| 665 " movq 128(%rsp), %xmm2\n" |
| 666 " movq 144(%rsp), %xmm3\n" |
| 667 " movq 160(%rsp), %xmm4\n" |
| 668 " movq 176(%rsp), %xmm5\n" |
| 669 " movq 192(%rsp), %xmm6\n" |
| 670 " movq 208(%rsp), %xmm7\n" |
| 671 " movq 224(%rsp), %xmm8\n" |
| 672 " movq 240(%rsp), %xmm9\n" |
| 673 " movq 256(%rsp), %xmm10\n" |
| 674 " movq 272(%rsp), %xmm11\n" |
| 675 " movq 288(%rsp), %xmm12\n" |
| 676 " movq 304(%rsp), %xmm13\n" |
| 677 " movq 320(%rsp), %xmm14\n" |
| 678 " movq 336(%rsp), %xmm15\n" |
| 679 "\n" |
| 680 " leaq 352(%rsp), %rsp\n" |
| 681 "\n" |
| 682 " jmp __afl_return\n" |
| 683 "\n" |
| 684 ".AFL_VARS:\n" |
| 685 "\n" |
| 686 |
| 687 #ifdef __APPLE__ |
| 688 |
| 689 " .comm __afl_area_ptr, 8\n" |
| 690 #ifndef COVERAGE_ONLY |
| 691 " .comm __afl_prev_loc, 8\n" |
| 692 #endif /* !COVERAGE_ONLY */ |
| 693 " .comm __afl_fork_pid, 4\n" |
| 694 " .comm __afl_temp, 4\n" |
| 695 " .comm __afl_setup_failure, 1\n" |
| 696 |
| 697 #else |
| 698 |
| 699 " .lcomm __afl_area_ptr, 8\n" |
| 700 #ifndef COVERAGE_ONLY |
| 701 " .lcomm __afl_prev_loc, 8\n" |
| 702 #endif /* !COVERAGE_ONLY */ |
| 703 " .lcomm __afl_fork_pid, 4\n" |
| 704 " .lcomm __afl_temp, 4\n" |
| 705 " .lcomm __afl_setup_failure, 1\n" |
| 706 |
| 707 #endif /* ^__APPLE__ */ |
| 708 |
| 709 " .comm __afl_global_area_ptr, 8, 8\n" |
| 710 "\n" |
| 711 ".AFL_SHM_ENV:\n" |
| 712 " .asciz \"" SHM_ENV_VAR "\"\n" |
| 713 "\n" |
| 714 "/* --- END --- */\n" |
| 715 "\n"; |
| 716 |
| 717 #endif /* !_HAVE_AFL_AS_H */ |
OLD | NEW |