Full Code of ZhangZhuoSJTU/StochFuzz for AI

master de10f62f3af9 cached
196 files
20.4 MB
240.6k tokens
419 symbols
1 requests
Download .txt
Showing preview only (916K chars total). Download the full file or copy to clipboard to get everything.
Repository: ZhangZhuoSJTU/StochFuzz
Branch: master
Commit: de10f62f3af9
Files: 196
Total size: 20.4 MB

Directory structure:
gitextract_uw9hr437/

├── .github/
│   └── workflows/
│       ├── basic.yml
│       ├── benchmark.yml
│       ├── early_instrumentation.yml
│       ├── force_linear.yml
│       ├── no_generic_pic.yml
│       └── pdisasm.yml
├── .gitignore
├── LICENSE
├── README.md
├── benchmark/
│   ├── boringssl-2016-02-12.inline
│   ├── boringssl-2016-02-12.normal
│   ├── boringssl-2016-02-12.seed
│   ├── c-ares-CVE-2016-5180.inline
│   ├── c-ares-CVE-2016-5180.normal
│   ├── c-ares-CVE-2016-5180.seed
│   ├── freetype2-2017.inline
│   ├── freetype2-2017.normal
│   ├── freetype2-2017.seed
│   ├── guetzli-2017-3-30.inline
│   ├── guetzli-2017-3-30.normal
│   ├── guetzli-2017-3-30.seed
│   ├── harfbuzz-1.3.2.inline
│   ├── harfbuzz-1.3.2.normal
│   ├── harfbuzz-1.3.2.seed
│   ├── json-2017-02-12.inline
│   ├── json-2017-02-12.normal
│   ├── json-2017-02-12.seed
│   ├── lcms-2017-03-21.inline
│   ├── lcms-2017-03-21.normal
│   ├── lcms-2017-03-21.seed
│   ├── libarchive-2017-01-04.inline
│   ├── libarchive-2017-01-04.normal
│   ├── libarchive-2017-01-04.seed
│   ├── libjpeg-turbo-07-2017.inline
│   ├── libjpeg-turbo-07-2017.normal
│   ├── libjpeg-turbo-07-2017.seed
│   ├── libpng-1.2.56.inline
│   ├── libpng-1.2.56.normal
│   ├── libpng-1.2.56.seed
│   ├── libssh-2017-1272.inline
│   ├── libssh-2017-1272.normal
│   ├── libssh-2017-1272.seed
│   ├── libxml2-v2.9.2.inline
│   ├── libxml2-v2.9.2.normal
│   ├── libxml2-v2.9.2.seed
│   ├── llvm-libcxxabi-2017-01-27.inline
│   ├── llvm-libcxxabi-2017-01-27.normal
│   ├── llvm-libcxxabi-2017-01-27.seed
│   ├── openssl-1.0.1f.inline
│   ├── openssl-1.0.1f.normal
│   ├── openssl-1.0.1f.seed
│   ├── openssl-1.0.2d.inline
│   ├── openssl-1.0.2d.normal
│   ├── openssl-1.0.2d.seed
│   ├── openssl-1.1.0c.inline
│   ├── openssl-1.1.0c.normal
│   ├── openssl-1.1.0c.seed
│   ├── openthread-2018-02-27.inline
│   ├── openthread-2018-02-27.normal
│   ├── openthread-2018-02-27.seed
│   ├── pcre2-10.00.inline
│   ├── pcre2-10.00.normal
│   ├── pcre2-10.00.seed
│   ├── proj4-2017-08-14.inline
│   ├── proj4-2017-08-14.normal
│   ├── proj4-2017-08-14.seed
│   ├── re2-2014-12-09.inline
│   ├── re2-2014-12-09.normal
│   ├── re2-2014-12-09.seed
│   ├── runtime/
│   │   ├── server.key
│   │   └── server.pem
│   ├── sqlite-2016-11-14.inline
│   ├── sqlite-2016-11-14.normal
│   ├── sqlite-2016-11-14.seed
│   ├── vorbis-2017-12-11.inline
│   ├── vorbis-2017-12-11.normal
│   ├── vorbis-2017-12-11.seed
│   ├── woff2-2016-05-06.inline
│   ├── woff2-2016-05-06.normal
│   ├── woff2-2016-05-06.seed
│   ├── wpantund-2018-02-27.inline
│   ├── wpantund-2018-02-27.normal
│   └── wpantund-2018-02-27.seed
├── build.sh
├── clean.sh
├── docs/
│   ├── system.md
│   ├── tips.md
│   ├── todo.md
│   └── trouble.md
├── scripts/
│   └── stochfuzz_env.sh
├── src/
│   ├── .clang-format
│   ├── Makefile
│   ├── address_dictionary.h
│   ├── afl_config.h
│   ├── asm_syscall.c
│   ├── asm_utils.c
│   ├── binary.c
│   ├── binary.h
│   ├── buffer.c
│   ├── buffer.h
│   ├── capstone_.c
│   ├── capstone_.h
│   ├── config.h
│   ├── core.c
│   ├── core.h
│   ├── crs_config.h
│   ├── diagnoser.c
│   ├── diagnoser.h
│   ├── disassembler.c
│   ├── disassembler.h
│   ├── elf_.c
│   ├── elf_.h
│   ├── fork_server.c
│   ├── fork_server.h
│   ├── frontend.c
│   ├── get_signal_stack_size.sh
│   ├── interval_splay.c
│   ├── interval_splay.h
│   ├── iterator.h
│   ├── library_functions/
│   │   ├── generate.py
│   │   ├── lib.csv
│   │   ├── library_functions.c
│   │   └── library_functions.h
│   ├── libstochfuzz.h
│   ├── libstochfuzzRT.c
│   ├── loader.c
│   ├── loader.h
│   ├── mem_file.c
│   ├── mem_file.h
│   ├── patcher.c
│   ├── patcher.h
│   ├── prob_disasm/
│   │   ├── prob_disasm_complete/
│   │   │   ├── dag.c
│   │   │   ├── hints.c
│   │   │   ├── propagation.c
│   │   │   └── solving.c
│   │   ├── prob_disasm_complete.c
│   │   └── prob_disasm_simple.c
│   ├── restricted_ptr.c
│   ├── restricted_ptr.h
│   ├── rewriter.c
│   ├── rewriter.h
│   ├── rewriter_handlers/
│   │   ├── generate.py
│   │   ├── handler_call.c
│   │   ├── handler_cjmp.c
│   │   ├── handler_jmp.c
│   │   ├── handler_loop.c
│   │   ├── handler_main.in
│   │   └── handler_ret.c
│   ├── sys_optarg.c
│   ├── sys_optarg.h
│   ├── tp_dispatcher.c
│   ├── tp_dispatcher.h
│   ├── trampolines/
│   │   ├── Makefile
│   │   ├── bitmap.c
│   │   ├── context_restore.c
│   │   ├── context_save.c
│   │   └── trampolines.h
│   ├── ucfg_analyzer.c
│   ├── ucfg_analyzer.h
│   ├── utils.c
│   ├── utils.h
│   └── x64_utils.c
└── test/
    ├── .crashpoint.z3
    ├── bzip2.no.pie
    ├── bzip2.pie
    ├── check_avx512
    ├── check_avx512.c
    ├── crash
    ├── crash.c
    ├── ex.smt2
    ├── hello
    ├── json-2017-02-12.normal
    ├── json.seed
    ├── leak-268f0e85f4bc45cbaf4d257222b830eac18977f3
    ├── libjpeg.asan
    ├── libpng-1.2.56
    ├── no_main
    ├── no_main.c
    ├── openssl-1.0.1f
    ├── openssl-1.0.1f.code.segments
    ├── pngfix.pie
    ├── rar
    ├── readelf.pie
    ├── runtime/
    │   ├── server.key
    │   └── server.pem
    ├── small_exec.elf
    ├── tcpdump.pie
    ├── test.c.bz2
    ├── test_daemon.sh
    ├── test_daemon_ignore_asan_sof.sh
    ├── timeout
    ├── timeout.c
    ├── unintentional_crash
    ├── unintentional_crash.c
    ├── vrrp.pcap
    └── z3

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/basic.yml
================================================
name: basic

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  schedule:
    - cron: 0 14 * * 1
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        id: cache
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}

      - name: set up python 3.x
        if: steps.cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
          architecture: 'x64'

      - name: install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          python -m pip install --upgrade pip meson ninja

      - name: build
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          ./build.sh
  
  debug:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make debug
        run: |
          clang --version
          make clean
          make debug
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test
        working-directory: ./src
  
  release:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test
        working-directory: ./src


================================================
FILE: .github/workflows/benchmark.yml
================================================
name: benchmark

on:
  push:
    branches:
      - "!*"
    tags:
      - "v*"
  schedule:
    - cron: 0 14 * * 1
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        id: cache
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}

      - name: set up python 3.x
        if: steps.cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
          architecture: 'x64'

      - name: install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          python -m pip install --upgrade pip meson ninja

      - name: build
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          ./build.sh

  normal:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make benchmark
        run: timeout --signal=KILL 35m make benchmark
        working-directory: ./src

  early_instrumentation:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make benchmark
        run: timeout --signal=KILL 35m make benchmark TEST_OPTIONS="-e"
        working-directory: ./src


================================================
FILE: .github/workflows/early_instrumentation.yml
================================================
name: early_instrumentation

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  schedule:
    - cron: 0 14 * * 1
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        id: cache
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}

      - name: set up python 3.x
        if: steps.cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
          architecture: 'x64'

      - name: install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          python -m pip install --upgrade pip meson ninja

      - name: build
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          ./build.sh
  
  debug:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make debug
        run: |
          clang --version
          make clean
          make debug
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-e'
        working-directory: ./src
  
  release:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-e'
        working-directory: ./src


================================================
FILE: .github/workflows/force_linear.yml
================================================
name: force_linear

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  schedule:
    - cron: 0 14 * * 1
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        id: cache
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}

      - name: set up python 3.x
        if: steps.cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
          architecture: 'x64'

      - name: install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          python -m pip install --upgrade pip meson ninja

      - name: build
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          ./build.sh
  
  debug:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make debug
        run: |
          clang --version
          make clean
          make debug
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-n'
        working-directory: ./src
  
  release:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-n'
        working-directory: ./src


================================================
FILE: .github/workflows/no_generic_pic.yml
================================================
name: no_generic_pic

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  schedule:
    - cron: 0 14 * * 1
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        id: cache
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}

      - name: set up python 3.x
        if: steps.cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
          architecture: 'x64'

      - name: install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          python -m pip install --upgrade pip meson ninja

      - name: build
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          ./build.sh
  
  debug:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make debug
        run: |
          clang --version
          make clean
          make debug
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-r'
        working-directory: ./src
  
  release:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-r'
        working-directory: ./src


================================================
FILE: .github/workflows/pdisasm.yml
================================================
name: pdisasm

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  schedule:
    - cron: 0 14 * * 1
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        id: cache
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}

      - name: set up python 3.x
        if: steps.cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
          architecture: 'x64'

      - name: install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          python -m pip install --upgrade pip meson ninja

      - name: build
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          ./build.sh
  
  release:
    runs-on: ubuntu-22.04
    needs: [build]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          path: |
            capstone/
            keystone/
            glib/
            libunwind/
          key: ${{ runner.os }}-${{ hashFiles('build.sh') }}
      - name: make format
        run: make format
        working-directory: ./src
      - name: make release
        run: |
          clang --version
          make clean
          make release
        working-directory: ./src
      - name: make test
        run: timeout --signal=KILL 30m make test TEST_OPTIONS='-f'
        working-directory: ./src


================================================
FILE: .gitignore
================================================
# Prerequisites
*.d

# Object files
*.o
*.ko
*.obj
*.elf

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

# Customize files
workshop/
capstone/ 
keystone/
glib/
libunwind/
AFL/
*.zip
*.swp
*.tmp
*.bin
*_bin.c
*.tp
*_tp.c
stoch-fuzz
*.gdb_history
peda*
handler_main.c
.stoch-fuzz.*
local_crashes
library_functions_load.c

# whitelist test
src/test/
test/*
!test/test_daemon.sh
!test/test_daemon_ignore_asan_sof.sh
!test/bzip2.no.pie
!test/test.c.bz2
!test/libpng-1.2.56
!test/seed.png
!test/crash
!test/crash.c
!test/openssl-1.0.1f
!test/openssl-1.0.1f.code.segments
!test/leak-268f0e85f4bc45cbaf4d257222b830eac18977f3
!test/runtime
!test/check_avx512.c
!test/check_avx512
!test/z3
!test/ex.smt2
!test/.crashpoint.z3
!test/hello
!test/test.rar
!test/rar
!test/timeout
!test/timeout.c
!test/unintentional_crash
!test/unintentional_crash.c
!test/no_main
!test/no_main.c
!test/json-2017-02-12.normal
!test/json.seed
!test/readelf.pie
!test/small_exec.elf
!test/bzip2.pie
!test/pngfix.pie
!test/toucan.png
!test/tcpdump.pie
!test/vrrp.pcap
!test/libjpeg.asan
!test/seed.jpg


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README.md
================================================
# StochFuzz: A New Solution for Binary-only Fuzzing <a href="https://openai.com/product/dall-e-2"><img src="imgs/logo.png" alt="Logo" align="right" width="72"/></a>

[![test](https://github.com/ZhangZhuoSJTU/StochFuzz/actions/workflows/basic.yml/badge.svg)](https://github.com/ZhangZhuoSJTU/StochFuzz/actions/workflows/basic.yml)
[![benchmark](https://github.com/ZhangZhuoSJTU/StochFuzz/actions/workflows/benchmark.yml/badge.svg)](https://github.com/ZhangZhuoSJTU/StochFuzz/actions/workflows/benchmark.yml)

<p>
<a href="https://github.com/ZhangZhuoSJTU/StochFuzz/blob/master/docs/stochfuzz.pdf"> <img title="" src="imgs/paper.png" alt="loading-ag-167" align="right" width="220"></a>

StochFuzz is a (probabilistically) sound and cost-effective fuzzing technique for stripped binaries. It is facilitated by a novel incremental and stochastic rewriting technique that is particularly suitable for binary-only fuzzing. Any AFL-based fuzzer, which takes edge coverage (defined by [AFL](https://github.com/google/AFL)) as runtime feedback, can acquire benefits from StochFuzz to directly fuzz stripped binaries.
</p>
  
More data and the results of the experiments can be found [here](https://github.com/ZhangZhuoSJTU/StochFuzz-data). Example cases of leveraging StochFuzz to improve advanced AFL-based fuzzers ([AFL++](https://github.com/AFLplusplus/AFLplusplus) and [Polyglot](https://github.com/s3team/Polyglot)) can be found in [system.md](docs/system.md#how-to-make-stochfuzz-compatible-with-other-afl-based-fuzzers).

## Clarifications

+ We adopt a new system design than the one from the paper. Details can be found at [system.md](docs/system.md).
+ In the paper, when we are talking about `e9patch`, we are actually talking about the binary-only fuzzing tool built upon e9patch, namely `e9tool`. Please refer to its [website](https://github.com/GJDuck/e9patch/blob/master/README.md#building) for more details.
+ StochFuzz provides sound rewriting for binaries without inlined data, and probabilistically sound rewriting for the rest.



## Building StochFuzz

StochFuzz is built upon [Keystone](https://www.keystone-engine.org/), [Capstone](https://www.capstone-engine.org/), [GLib](https://developer.gnome.org/glib/), and [libunwind](https://www.nongnu.org/libunwind/).

Most of these depenences require `meson >= 0.60.1`. Please use `meson --version` to check you are using the up-to-date version.

[Build.sh](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/master/build.sh) helps build all the dependences automatically. For clean containers, make sure some standard tools like `autoreconf` and `libtool` are installed.
 
```bash
$ git clone https://github.com/ZhangZhuoSJTU/StochFuzz.git
$ cd StochFuzz
$ ./build.sh
```

StochFuzz itself can be built by GNU Make.

```bash
$ cd src
$ make release
```

We have tested StochFuzz on Ubuntu 18.04. If you have any issue when running StochFuzz on other systems, please kindly let us [know](https://github.com/ZhangZhuoSJTU/StochFuzz/issues/new).

## How to Use

StochFuzz provides multiple rewriting options, which follows the AFL's style of passing arguments.

```
$ ./stoch-fuzz -h
stoch-fuzz 1.0.0 by <zhan3299@purdue.edu>

./stoch-fuzz [ options ] -- target_binary [ ... ]

Mode settings:

  -S            - start a background daemon and wait for a fuzzer to attach (defualt mode)
  -R            - dry run target_binary with given arguments without an attached fuzzer
  -P            - patch target_binary without incremental rewriting
  -D            - probabilistic disassembly without rewriting
  -V            - show currently observed breakpoints

Rewriting settings:

  -g            - trace previous PC
  -c            - count the number of basic blocks with conflicting hash values
  -d            - disable instrumentation optimization
  -r            - assume the return addresses are only used by RET instructions
  -e            - install the fork server at the entrypoint instead of the main function
  -f            - forcedly assume there is data interleaving with code
  -i            - ignore the call-fallthrough edges to defense RET-misusing obfuscation

Other stuff:

  -h            - print this help
  -x execs      - set the number of executions after which a checking run will be triggered
                  set it as zero to disable checking runs (default: 200000)
  -t msec       - set the timeout for each daemon-triggering execution
                  set it as zero to ignore the timeout (default: 2000 ms)
  -l level      - set the log level, including INFO, WARN, ERROR, and FATAL (default: INFO)

```


### Basic Usage

```diff
- It is worth first trying the advanced strategy (see below) because that is much more cost-effective.
```

To fuzz a stripped binary, namely `example.out`, we need to `cd` to the directory of the target binary. For example, if the full path of `example.out` is `/root/example.out`, we need to first `cd /root/`. Furthermore, _it is dangerous to run two StochFuzz instances under the same directory._ These restrictions are caused by some design faults and we will try to relax them in the future. 

Assuming StochFuzz is located at `/root/StochFuzz/src/stoch-fuzz`, execute the following command to start rewriting the target binary.

```bash
$ cd /root/
$ /root/StochFuzz/src/stoch-fuzz -- example.out # do not use ./example.out here
```

After the initial rewriting, we will get a phantom file named `example.out.phantom`. This phantom file can be directly fuzzed by AFL or any AFL-based fuzzer. Note that the StochFuzz process would not stop during fuzzing, so please make sure the process is alive during fuzzing.

Here is a demo that shows how StochFuzz works.

[![asciicast](https://asciinema.org/a/415987.svg)](https://asciinema.org/a/415987)

### Advanced Usage

Compared with the compiler-based instrumentation (e.g., afl-clang-fast), StochFuzz has additional runtime overhead because it needs to emulate each _CALL_ instruction to support stack unwinding.

Inspired by a recent [work](https://dl.acm.org/doi/abs/10.1145/3445814.3446765), we provide an advanced rewriting strategy where we do not emulate _CALL_ instructions but wrap the `_ULx86_64_step` function from [libunwind](https://github.com/libunwind/libunwind) to support stack unwinding. This strategy works for most binaries but may fail in some cases like fuzzing statically linked binaries.

To enable such strategy, simply provide a __-r__ option to StochFuzz.

```bash
$ cd /root/
$ /root/StochFuzz/src/stoch-fuzz -r -- example.out # do not use ./example.out here
```

Addtionally, before fuzzing, we need to prepare the `AFL_PRELOAD` environment variable for AFL.

```bash
$ export STOCHFUZZ_PRELOAD=$(/root/StochFuzz/scritps/stochfuzz_env.sh)
$ AFL_PRELOAD=$STOCHFUZZ_PRELOAD afl-fuzz -i seeds -o output -t 2000 -- example.out.phantom @@
```

Following demo shows how to apply this advanced strategy.

[![asciicast](https://asciinema.org/a/416230.svg)](https://asciinema.org/a/416230)

## Troubleshootings

Common issues can be referred to [trouble.md](docs/trouble.md). If it cannot help solve your problem, please kindly open a Github issue.

Besides, we provide some tips on using StochFuzz, which can be found at [tips.md](docs/tips.md)

## Development

Currently, we have many todo items. We present them in [todo.md](docs/todo.md#todo-list). 

We also present many pending decisions which we are hesitating to take, in [todo.md](docs/todo.md#challenges). __If you have any thought/suggestion, do not hesitate to let us know.__ It would be very appreciated if you can help us improve StochFuzz.

StochFuzz should be considered an alpha-quality software and it is likely to contain bugs. 

I will try my best to maintain StochFuzz timely, but sometimes it may take me more time to respond. Thanks for your understanding in advance.

## Cite

Zhang, Zhuo, et al. "STOCHFUZZ: Sound and Cost-effective Fuzzing of Stripped Binaries by Incremental and Stochastic Rewriting." 2021 IEEE Symposium on Security and Privacy (SP). IEEE, 2021.

## References

+ Duck, Gregory J., Xiang Gao, and Abhik Roychoudhury. "Binary rewriting without control flow recovery." Proceedings of the 41st ACM SIGPLAN Conference on Programming Language Design and Implementation. 2020.
+ Meng, Xiaozhu, and Weijie Liu. "Incremental CFG patching for binary rewriting." Proceedings of the 26th ACM International Conference on Architectural Support for Programming Languages and Operating Systems. 2021.
+ Aschermann, Cornelius, et al. "Ijon: Exploring deep state spaces via fuzzing." 2020 IEEE Symposium on Security and Privacy (SP). IEEE, 2020.
+ Google. “Google/AFL.” GitHub, github.com/google/AFL. 


================================================
FILE: benchmark/json-2017-02-12.seed
================================================
10000000010E5


================================================
FILE: benchmark/llvm-libcxxabi-2017-01-27.seed
================================================
ZUlSaIJT_2_EET_E5


================================================
FILE: benchmark/pcre2-10.00.seed
================================================
# This is a specialized test for checking, when PCRE2 is compiled with the
# EBCDIC option but in an ASCII environment, that newline and white space
# functionality is working. It catches cases where explicit values such as 0x0a
# have been used instead of names like CHAR_LF. Needless to say, it is not a
# genuine EBCDIC test! In patterns, alphabetic characters that follow a
# backslash must be in EBCDIC code. In data, NL, NEL, LF, ESC, and DEL must be
# in EBCDIC, but can of course be specified as escapes.

# Test default newline and variations

/^A/m
    ABC
    12\x15ABC

/^A/m,newline=any
    12\x15ABC
    12\x0dABC
    12\x0d\x15ABC
    12\x25ABC

/^A/m,newline=anycrlf
    12\x15ABC
    12\x0dABC
    12\x0d\x15ABC
    ** Fail
    12\x25ABC

# Test \h

/^A\/
    A B

# Test \H

/^A\/
    AB
    ** Fail
    A B

# Test \R

/^A\/
    A\x15B
    A\x0dB
    A\x25B
    A\x0bB
    A\x0cB
    ** Fail
    A B

# Test \v

/^A\/
    A\x15B
    A\x0dB
    A\x25B
    A\x0bB
    A\x0cB
    ** Fail
    A B

# Test \V

/^A\/
    A B
    ** Fail
    A\x15B
    A\x0dB
    A\x25B
    A\x0bB
    A\x0cB
    
# For repeated items, use an atomic group so that the output is the same
# for DFA matching (otherwise it may show multiple matches).

# Test \h+

/^A(?>\+)/
    A B

# Test \H+

/^A(?>\+)/
    AB
    ** Fail
    A B

# Test \R+

/^A(?>\+)/
    A\x15B
    A\x0dB
    A\x25B
    A\x0bB
    A\x0cB
    ** Fail
    A B

# Test \v+

/^A(?>\+)/
    A\x15B
    A\x0dB
    A\x25B
    A\x0bB
    A\x0cB
    ** Fail
    A B

# Test \V+

/^A(?>\+)/
    A B
    ** Fail
    A\x15B
    A\x0dB
    A\x25B
    A\x0bB
    A\x0cB

# End


================================================
FILE: benchmark/runtime/server.key
================================================
-----BEGIN PRIVATE KEY-----
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA1AdZNDVOA9cXm97f
erp1bukz2kohjToJS6Ma8fOb36VV9lQGmDNsJanXFiqafOgV+kh1HXqZ3l1I0JmZ
71b+QQIDAQABAkAHGfPn5r0lLcgRpWZQwvv56f+dmQwEoeP7z4uwfNtEo0JcRD66
1WRCvx3LE0VbNeaEdNmSPiRXhlwIggjfrBi9AiEA9UusPBcEp/QcPGs96nQQdQzE
fw4x0HL/eSV3qHimT6MCIQDdSAiX4Ouxoiwn/9KhDMcZXRYX/OPzj6w8u1YIH7BI
ywIgSozbJdAhHCJ2ym4VfUIVFl3xAmSAA0hQGLOocE1qzl0CIQDRicOxZmhqBiKA
IgznOn1StEYWov+MhRFZVSBLgw5gbwIgJzOlSlu0Y22hEUsLCKyHBrCAZZHcZ020
20pfogmQYn0=
-----END PRIVATE KEY-----


================================================
FILE: benchmark/runtime/server.pem
================================================
-----BEGIN CERTIFICATE-----
MIIBYTCCAQugAwIBAgIJAMPQQtUHkx+KMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNV
BAMMAWEwHhcNMTYwOTI0MjIyMDUyWhcNNDQwMjA5MjIyMDUyWjAMMQowCAYDVQQD
DAFhMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANQHWTQ1TgPXF5ve33q6dW7pM9pK
IY06CUujGvHzm9+lVfZUBpgzbCWp1xYqmnzoFfpIdR16md5dSNCZme9W/kECAwEA
AaNQME4wHQYDVR0OBBYEFCXtEo9rkLuKGSlm0mFE4Yk/HDJVMB8GA1UdIwQYMBaA
FCXtEo9rkLuKGSlm0mFE4Yk/HDJVMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADQQCnldOnbdNJZxBO/J+979Urg8qDp8MnlN0979AmK1P5/YzPnAF4BU7QTOTE
imS5qZ0MvziBa81nVlnnFRkIezcD
-----END CERTIFICATE-----


================================================
FILE: benchmark/sqlite-2016-11-14.seed
================================================
 SELECT 888<8888888 | daDROPme(1,1 
,11,1 
,1)| 388<8888888 | datetime(1,1 ,11,1 
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<7777777777777888888<88,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<77774777777777888888<8888888 
,11,1 
,1)| 194<8888888 | dattime(1,1 
,1)|8 | datetime(88
,1)|8 | datetime(11,1 
,1)| ( SELECT 8878888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| 388<8888888 | datetime(1,1 
,1,1 
,1)|8 | ANALYZEe(1,1 
,1)| ( SELECT 887<$$$$$$$02e777777 || 888<(7777777777777<888888
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<777377777 | datetime(1,1 
,1,1 
,1)|8 | datetime| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<7777777777777888888<88,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<77774777777777888888<8888888 
,11,1 
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(88
,1)|8 | datetime(1,1 
,1)| ( SELECT 8878888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( (E1 
,1 
,1)| 388<8888888 | d$$BETWEE,1)|8 | datetime(1,1 
,1)| ( SELECT 887<777777,1)|8 | datetime(1,1 
,1)| ( SELECT 887<$$$$$$$02e777777 ||888 | datetimf(1,1 
,1)|8 | datetime(1,1 
,1)| 388<888888888888777888888<88,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<77774777777777888888<8888888 
,11,1 
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datet(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<77888888
,1)|8 |etime(1,1 
,1)| 388<8888888 | datetime(1,188<8888888 | datetime(1,1| datetime(1,1 
,1)| ( SELECT  y  in
(1,1 
,1)| ( SELECT 81 
,1)|8 | date|etime(1,1 
,1)| 388<8888888 | datetime(1,188<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT  y  in
m e_crash$$
,1)| 38
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetimetetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT  y  in
m e_crash$$
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT  y  in
(1,1 
,1)| ( SELECT 81 
,1)|8 | datetime(1,1 
,1)| ( SELECT  y  in
m e_crash$$
,e(1,1 
,1)| ( SELECT  y  in
m e_crash$$
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT  y  in
(1,1 
,1)| ( SELECT 81 
,1)|8 | datet)| 388<8888888 | datetime(1,1 
,1,0 
,1)|8 | ANALYZEe(1,1 
,1)| ( SELECT 887<$$$$$$$02e777777 || 888<7777777777777<888888
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<777377777 | datetime(1,1 
,1,1 
,11 
,1)| ( SELECT87<77888888
,1)|8 |etime(1,1  datetime(1,1 
,1)| ( SELECT  y  in
m e_crash$$
,1)| 388<88888
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT 887<77888888
,1)|8 |etime(1,1 
,1)| 388<8888888 | datetime(1,188<8888888 | datetime(1,1 
,1)|8 | datetime(1,1 
,1)| ( SELECT  y  in
m e_crash$$
,1)| 38
,1)| 388<8888888 | datetime(1,1 
,1)|8 | datetime(1,reload1 
,1)| ( SELECT  y  in
m (1)  SELECT 8 87<577777

================================================
FILE: benchmark/wpantund-2018-02-27.seed
================================================
0ConfiG:NCP:SocketPath "/dev/null"
Config:NCP:SocketPath "/dev/null"


================================================
FILE: build.sh
================================================
#!/bin/bash

RED="\033[31m"
GREEN="\033[32m"
YELLOW="\033[33m"
BOLD="\033[1m"
OFF="\033[0m"

CAPSTONE_VERSION="4.0.2"
KEYSTONE_VERSION="0.9.2"
GLIB_VERSION="2.72.0"
LIBUNWIND_VERSION="1.5"

set -e

#
# check necessary command
#

check_command () {
    for cmd in $@
    do
        if [ ! -x "$(command -v $cmd)" ]; then
            echo -e "${RED}Error${OFF}: $cmd is not installed." >&2
            exit 1
        fi
    done
}

check_command "wget" "unzip" "make" "cmake" "meson" "ninja" "pkg-config" "clang" "python3"

#
# check clang version (>= 6.0.0)
#

CLANG_VERSION=$(clang --version | head -n 1 | grep -o -E "[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+" | uniq | sort)
CLANG_MAJOR_VERSION=$(echo $CLANG_VERSION | awk -F '.' '{ print $1 }')
if [[ $CLANG_VERSION < "6.0.0" && ${#CLANG_MAJOR_VERSION} = "1" ]]; then
    echo "clang-6.0 or a newer version is required"
    exit 1
fi


#
# build capstone
#

CAPSTONE_URL="https://github.com/aquynh/capstone/archive/$CAPSTONE_VERSION.zip"

if [ ! -d capstone ]
then
    if [ ! -f capstone.zip ]
    then
        echo -e "${GREEN}$0${OFF}: downloading capstone.zip..."
        wget -O capstone.zip $CAPSTONE_URL
    fi

    echo -e "${GREEN}$0${OFF}: extracting capstone.zip..."
    unzip capstone.zip
    mv capstone-$CAPSTONE_VERSION capstone

    echo -e "${GREEN}$0${OFF}: building capstone.zip..."
    cd capstone
    CAPSTONE_DIET=no CAPSTONE_X86_REDUCE=no CAPSTONE_ARCHS="x86" ./make.sh
    cd ..
fi


#
# build keystone
#

KEYSTONE_URL="https://github.com/keystone-engine/keystone/archive/$KEYSTONE_VERSION.zip"

if [ ! -d keystone ]
then
    if [ ! -f keystone.zip ]
    then
        echo -e "${GREEN}$0${OFF}: downloading keystone.zip..."
        wget -O keystone.zip $KEYSTONE_URL
    fi

    echo -e "${GREEN}$0${OFF}: extracting keystone.zip..."
    unzip keystone.zip
    mv keystone-$KEYSTONE_VERSION keystone

    echo -e "${GREEN}$0${OFF}: building keystone.zip..."
    cd keystone
    if [ -d build ]
    then
        rm -rf build
    fi
    mkdir build
    cd build
    cmake -DBUILD_LIBS_ONLY=1 -DLLVM_BUILD_32_BITS=0 -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DLLVM_TARGETS_TO_BUILD="AArch64;X86" -G "Unix Makefiles" ..
    make -j8
    cd ../..
fi


#
# build glib
#

GLIB_URL="https://github.com/GNOME/glib/archive/$GLIB_VERSION.zip"

if [ ! -d glib ]
then
    if [ ! -f glib.zip ]
    then
        echo -e "${GREEN}$0${OFF}: downloading glib.zip..."
        wget -O glib.zip $GLIB_URL
    fi

    echo -e "${GREEN}$0${OFF}: extracting glib.zip..."
    unzip glib.zip
    mv glib-$GLIB_VERSION glib

    echo -e "${GREEN}$0${OFF}: building glib.zip..."
    cd glib
    meson _build --buildtype=release --default-library=static --prefix=$(realpath .)
    ninja -C _build
    ninja -C _build install
    cd ..
fi

#
# build libunwind
#

LIBUNWIND_URL="https://github.com/libunwind/libunwind/archive/v$LIBUNWIND_VERSION.zip"

if [ ! -d libunwind ]
then
    if [ ! -f libunwind.zip ]
    then
        echo -e "${GREEN}$0${OFF}: downloading libunwind.zip..."
        wget -O libunwind.zip $LIBUNWIND_URL
    fi

    echo -e "${GREEN}$0${OFF}: extracting libunwind.zip..."
    unzip libunwind.zip
    mv libunwind-$LIBUNWIND_VERSION libunwind

    echo -e "${GREEN}$0${OFF}: building libunwind.zip..."
    cd libunwind
    mkdir install
    ./autogen.sh
    ./configure --prefix=`pwd`/install --enable-cxx-exceptions
    make install -j8
    cd ..
fi

#
# build src
#

# cd src
# make release


================================================
FILE: clean.sh
================================================
#!/bin/bash

if [ -d capstone ]
then
    rm -rf capstone
fi

if [ -d keystone ]
then
    rm -rf keystone
fi

if [ -d glib ]
then
    rm -rf glib
fi

if [ -d libunwind ]
then
    rm -rf libunwind
fi

rm -rf *.zip

cd src && make clean


================================================
FILE: docs/system.md
================================================
# New System Design

Originally, StochFuzz was integrated into AFL, which made an easy development. However, as more and more advanced fuzzing tools (e.g., [Polyglot](https://github.com/s3team/Polyglot)) take their own implementations (e.g., developing a new variant of AFL), it becomes hard to combine StochFuzz with these tools. 

As such, we decide to separate StochFuzz and AFL. With this new system design, any AFL-based fuzzer can directly fuzz the phantom binary generated by StochFuzz.

However, it also brings some new challenges. 

First of all, it is easy for the old design to keep multiple versions of rewritten binaries at the same time (by modifying AFL to set up multiple fork servers), but not for the new one. Currently, StochFuzz is independent of AFL, which means it can only keep a single binary at a time. Hence, to detect those erroneous rewriting errors only changing execution paths but not triggering crashes, we introduce a new technique named __checking executions__. These checking executions are triggered periodically and check the coverage consistency w/ and w/o uncertain patchings. After each checking execution, the rewritten binary will get changed. `-x` option is for checking runnings.

Besides, we need to manually set the timeout for StochFuzz, which should be consistent with the one of AFL. `-t` option is for the timeout.

A good observation is that the edge coverage is at the block level, which means we do not need to trap all instructions but one instruction per block. This observation helps us avoid many rewriting errors.

## How to make StochFuzz compatible with other AFL-based fuzzers

One of the most common practices of variants of [AFL](https://github.com/google/AFL) is to extend the size of the shared memory. For example, [AFL++](https://github.com/AFLplusplus/AFLplusplus) extends the size to [8388608](https://github.com/AFLplusplus/AFLplusplus/blob/48c878a76ddec2c133fd5708b185b2ac27740084/include/config.h#L44) bytes (`1 << 23`). To make StochFuzz compatible with such AFL variants, we need to do some slight modifications.

Specifically, we need to modify two macros defined in [afl_config.h](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/master/src/afl_config.h), [AFL_MAP_SIZE_POW2](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/9fe1500791729e267894e44faa935757e13124e6/src/afl_config.h#L37) and [AFL_MAP_ADDR](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/9fe1500791729e267894e44faa935757e13124e6/src/afl_config.h#L39). 

__AFL_MAP_SIZE_POW2__ is the logarithm of the size to the base 2. For example, to support AFL++, AFL_MAP_SIZE_POW2 should be set to 23: <img src="https://render.githubusercontent.com/render/math?math=log_2 8388608 = 23">.

__AFL_MAP_ADDR__ is the address of the shared memory in the subject binary. Based on our testing, 0x3000000 would be a safe address.

In short, taking AFL++ as an example, following modifications are sufficient.

```c
#define AFL_MAP_SIZE_POW2 23
#define AFL_MAP_ADDR 0x3000000
```

## Case: Polyglot

[Polyglot](https://github.com/s3team/Polyglot) is a state-of-the-art language fuzzer that focuses on testing compilers and language interpreters. Since many programming languages are bootstrapping, which means their language processors are written in themselves, it is difficult or time-consuming to instrument these processors (e.g., __GCC__). The developers of Polyglot originally used AFL-QEMU mode to test such processors. 

In this case study, we try to combine Polyglot with StochFuzz to provide a more efficient fuzzing test for GCC. 

Before starting our experiments, we need to make a slight change on StochFuzz. Since the developers of Polyglot extend the [size of AFL shared memory](https://github.com/s3team/Polyglot/blob/a49f67ffb95684ae2227800a85eb7963eeb2692d/AFL_replace_mutate/config.h#L323), we need to update it in StochFuzz accordingly.

Specifically, we need first to change [AFL_MAP_SIZE_POW2](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/f90db25c300e79b9dd37748da883cb9d66a8253f/src/afl_config.h#L37) to 20. To avoid the conflicts of mmap, we additionally need to change [AFL_MAP_ADDR](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/f90db25c300e79b9dd37748da883cb9d66a8253f/src/afl_config.h#L39). I set it as 0x180000 in this case. The new [afl_config.h](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/f90db25c300e79b9dd37748da883cb9d66a8253f/src/afl_config.h) would look like:

```c
...
#define AFL_FORKSRV_FD 198
#define AFL_SHM_ENV "__AFL_SHM_ID"
#define AFL_MAP_SIZE_POW2 20 
#define AFL_MAP_SIZE (1 << AFL_MAP_SIZE_POW2)
#define AFL_MAP_ADDR 0x180000
#define AFL_PREV_ID_PTR (RW_PAGE_ADDR + 0x8)
#define AFL_MAP_SIZE_MASK ((1 << AFL_MAP_SIZE_POW2) - 1)
...
```

We apply the [advanced strategy](https://github.com/ZhangZhuoSJTU/StochFuzz#advanced-usage) of StochFuzz and run two GCC fuzzing instances, including `Polyglot + StochFuzz` and `Polyglot + AFL-QEMU`, for 24 hours.

### Screenshot

![screenshots](../imgs/polyglot_screenshot.png)

In the above screenshot, the top left and bottom left panels show the progresses of `Polyglot + StochFuzz` and `Polyglot + AFL-QEMU`, respectively. The right panel shows some logging information of StochFuzz.

In short, when running for around 20 minutes, StochFuzz can achieve 70 executions per second while AFL-QEMU only 4 executions per seconds. In the meantime, StochFuzz found 6520 paths, two times more than AFL-QEMU did (2169 paths). Our register liveness analysis helps StochFuzz avoid _98.4%_ saving/restoring for FLAGS register and _81.2%_ for general purpose registers.

### Results

<p float="center">
  <img title="" src="../imgs/polyglot_path.png" height="280">
  <img title="" src="../imgs/polyglot_eps.png" height="280">
</p>

The left figure presents how many paths each tool found over time. The blue solid line is for StochFuzz and the orange dotted line is for AFL-QEMU. We can see at the end, StochFuzz found much more paths than AFL-QEMU.

The right figure presents the distribution of EPS (executions per second) of two tools, the blue one for StochFuzz and the orange one for AFL-QEMU. The average EPS of StochFuzz is around 60 executions per second, nearly 7 times faster than AFL-QEMU.


================================================
FILE: docs/tips.md
================================================
# Tips

To enable a more effective and efficient fuzzing, we provide several tips about better using StochFuzz. 

## Advanced Strategy

As mentioned in [README.md](../README.md#advanced-usage), we strongly recommend every user first tries the advanced strategy.

StochFuzz tries to provide a conservative rewriting. As such, it emulates all the _CALL_ instructions to maintain an unchanged data flow. 

However, in most cases, the return addresses pushed by _CALL_ instructions are only used by _RET_ instructions and the stack unwinding. Based on this observation, we provide an advanced rewriting strategy that hooks the process of stack unwinding and hence does not need to emulate _CALL_ instructions. This strategy is quite efficient and can reduce around 80% overhead of StochFuzz.

The advanced strategy can be applied to most binaries but will cause rewriting errors on some including:

+ statically-linked binaries that do online stack unwinding
+ some CFI-protected binaries
+ some go-written binary
+ ...

How to adopt the advanced rewriting strategy can be found in [README.md](../README.md#advanced-usage).

## Timeout

StochFuzz needs to specify a timeout for any execution caused by the increment rewriting. The timeout is configured by the `-t` option.

```
  -t msec       - set the timeout for each daemon-triggering execution
                  set it as zero to ignore the timeout (default: 2000 ms)
```

AFL, or any attached AFL-based fuzzer, needs to specify a timeout either. We recommend that the two timeouts should be set consistently, but it is not mandatory. 

However, for the binaries with inlined data, the timeout set for the attached fuzzer should __BE LARGER THAN 1000MS__. Otherwise, the auto-scaling feature of AFL timeout will cause incorrect error diagnosis during the stochastic rewriting. 

## Checking Executions

As we mentioned in [system.md](system.md), we adopt a new system design to have a wide application in the fields of binary-only fuzzing. This new architecture design is enabled by the observation that we only need to instrument an instruction per basic block to collect the code coverage of AFL and is facilitated by a new technique named checking executions. 

Technically speaking, checking executions are triggered periodically and to check whether the collected coverages are consistent with and without uncertain patches. 

The `-x` option is provided for configuring the checking executions, setting the number of executions after which a checking execution will be triggered.  

```
  -x execs      - set the number of executions after which a checking run will be triggered
                  set it as zero to disable checking runs (default: 200000)
```

For example, if we provide `-x 1000`, it means a checking execution will be triggered every 1000 AFL executions. 

The period of checking executions affects the fuzzing effectiveness. Intuitively, the more checking executions we have, the more overhead they cause. The overhead caused by checking executions is <img src="https://render.githubusercontent.com/render/math?math=\large \frac{1}{M}">
, where a checking execution is triggered every _M_ normal executions.

The period of checking executions also affects the probabilistic soundness we provided. Let's additionally assume that the probability of a given rewriting error changing the execution path is _p_. Then, we will have that, the probability _P_ that a rewriting error cannot be detected after the total _N_ executions is <img src="https://render.githubusercontent.com/render/math?math=\large (1 - p)^\frac{N}{M}">.

In a nutshell, the larger number we set, the fewer check executions we will take. In other words, the larger number we set, the more cost-effective but the less probabilistically sound the fuzzing is.

For example, if _M = 1000_, _p = 1e-4_, _N = 1e8_. The overhead caused by checking executions is _0.1%_ and the probability of have an undetected rewriting error is _4.5e-5_.

The user may need to provide a suitable number. __A NUMBER LARGER THAN 200 IS RECOMMENDED__. 

Note that this option is useful only when the inlined data is presented. To eliminate the overhead caused by checking executions, we additionally plan to set up two different fuzzing instances like what [QSYM](https://github.com/sslab-gatech/qsym) does, where one is for fuzzing and the other is for checking executions.


================================================
FILE: docs/todo.md
================================================
# Development Plan

## Todo List

While we have successfully migrated StochFuzz to a new system design, we can still improve StochFuzz from multiple places.

+ [x] __NEW SYSTEM DESIGN__ (daemon), which separates AFL and StochFuzz and makes advanced fuzzing possible.
+ [x] In release version, remove unnecessary z\_log (e.g., z\_debug, z\_trace, and etc.).
+ [x] Support probabilisitic disassembly.
+ [x] Mark .text section non-writable.
+ [x] Support C++ exceptions (via pushing the original ret\_addr onto the stack).
+ [x] When a CP\_RETADDR is found, support updating other CP\_RETADDR from the same callee.
+ [x] Use-def analysis on EFLAG register to avoid unnecessary context switching.
+ [x] Support pre-disassembly (linear disassembly) -- IT SEEMS NOT A GOOD IDEA.
+ [x] Support `jrcxz` and `jecxz` instructions.
+ [x] It may be a good idea to additionally hook SIGILL caused by mis-patched instructions. In that design, exiting the program with a specific status code (in SIGSEGV handler) is a better approach, compared with raising SIGILL. It can also avoid recursive signal handling.
+ [x] Support retaddr patch when pdisasm is enabled (check retaddr's probability) -- it seems impossible. Note that we cannot guarantee the control flow is returned from the callee even the returen address is visited.
+ [x] A better frontend for passing arguments.
+ [x] Use runtime arguments to set different modes, instead of makefile.
+ [x] Use simple linear disassembly to check the existence of inlined data.
+ [x] Read PLT table to get library functions' names, and support the white-list for library functions.
+ [x] Correctly handle timeout from AFL.
+ [x] Use shared memory for .text section, to avoid the expensive patch commands.
+ [x] Support self-correction procedure (delta debugging).
+ [x] Support non-return analysis on UCFG, with the help of the white-list for library functions.
+ [x] Support the on-the-fly probability recalculation.
+ [x] Add a new flag/option to enable early instrumentation for fork server (i.e., before the entrypoint of binary).
+ [x] Enable periodic checking (for coverage feedback) to determine those false postives which do not lead to crashes.
+ [x] Add tailed invalid instructions for those basic blocks terminated by bad decoding.
+ [x] Add a license.
+ [x] Do not use a global sys\_config, but put the options into each object.
+ [x] Current TP\_EMIT is only compatible with fuzzers compiled with AFL\_MAP\_SIZE = (1 << 16), we need to change the underlying implementation of TP\_EMIT to automatically fit the AFL\_MAP\_SIZE.
+ [x] Fix the bugs when rewriting PIE binary and support it.
+ [x] Place `ENDBR64` instruction before the AFL trampoline. The phantom program will crash otherwise.
+ [x] Support binaries compiled with gcc ASAN (clang would inline ASAN functions).
+ [ ] Use g\_hash\_table\_iter\_init instead of g\_hash\_table\_get\_keys.
+ [ ] Apply AddrDict to all possible places..
+ [ ] Apply Iter to all possible places..
+ [ ] Support other disassembly backends, for the initial disassembly (e.g., [XDA](https://github.com/CUMLSec/XDA)).
+ [ ] Calculate [entropy](https://github.com/NationalSecurityAgency/ghidra/issues/1035) to check the existence of inlined data (ADVANCED).
+ [ ] Remove legacy code (e.g., the function of building bridges by Rewriter is no longer needed).
+ [ ] Instead of patching a fixed invalid instruction (0x2f), randomly choose an invalid instruction to patch. More details can be found [here](http://ref.x86asm.net/coder64.html).
+ [ ] Automatically scale the number of executions triggering checking runs (based on the result of previous checking run).
+ [ ] Set the default log level as WARN (note that we need to update `make test` and `make benchmark`).
+ [ ] Use a general method to add segments in the given ELF instead of using the simple PT\_NOTE trick.
+ [ ] Fix the failed Github Actions on Ubuntu 20.04 (the root cause is unknown currently).
+ [ ] Add more stress test for rewriting PIE binary.
+ [ ] Support binaries compiled with MSAN.


## Challenges

We additionally have some challenges which may cause troubles or make StochFuzz not that easy to use. We are trying to resolve them.

+ The fixed LOOKUP\_TABLE\_ADDR is mixed with other random addresses, which may cause bugs in PIE binary.
+ The glibc code contains some overlapping instructions (e.g., the [instructions with the LOCK prefix](https://code.woboq.org/userspace/glibc/sysdeps/x86/atomic-machine.h.html#_M/__arch_c_compare_and_exchange_val_8_acq)), which may cause troubles for the patcher and pdisasm.

There are some other challenges introduced by the [new system design](system.md).

+ The input file may be changed by the previous crashed executing, which makes the next execution incorrect. But it seems ok in practice, because fuzzing is a highly repeative procedure which can fix the incorrect feedback automatically and quickly.
+ Timeout needs to be set up separately for AFL and StochFuzz, which may bother the users a little bit.
+ The auto-scaled timeout of AFL may cause incorrect error diagnosis (the [dd\_status](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/master/src/diagnoser.h#L91) may be invalid), so it is highly recommended to specify a timeout (>= 1000ms or >= AFL\_HANG\_TMOUT if set) for AFL by `-t` option, to disable the feature of auto-scaled timeout.

Note that in the old design, we can fully control AFL, so that we can _create a new input file for the next execution_, _use the same timeout_, or _disable the auto-scaled timeout_ to avoid aforementioned challenges.

## Pending Development Decisions

Currently, there are many steps which we are hesitating to take. We may need to carefully evaluate them. __If you have any suggestion, please kindly let us know__. We are happy to take any possible discussion about improving StochFuzz.

+ Currently, we use a lookup table to translate indirect call/jump on the fly. We are not sure whether it is necessary because simply patching a jump instruction at the target address may also work well. Note that a large lookup table may increase the cache missing rate and the overhead of process forking.
+ For now, to support the [advanced strategy](https://github.com/ZhangZhuoSJTU/StochFuzz#advanced-usage), we maintain a retaddr mapping and do _O(log n)_ online binary searching to find the original retaddr when unwinding stack. It may be better to maintain a retaddr lookup table which supports _O(1)_ looking up. But also, this lookup table will extremely increase the memory usage as well as the cache missing rate and the overhead of process forking.
+ Hook more signals to collect address information for a better error diagnosis, which, on the other hand, may cause conflicts of signal handlers set by the subject program.


================================================
FILE: docs/trouble.md
================================================
# Troubleshootings

If you are using a variant of AFL instead of the original [AFL](https://github.com/google/AFL), please refer to [system.md](https://github.com/ZhangZhuoSJTU/StochFuzz/blob/master/docs/system.md#how-to-make-stochfuzz-compatible-with-other-afl-based-fuzzers) which tells you how to make StochFuzz compatible with those variants.

Besides, this documentation mainly talks about how to handle the case where the rewritten binaries have inconsistent behaviors taking the same inputs (e.g., invalid crashes which cannot be reproduced by the original binaries). Please kindly open an issue to report any other problem, including:

+ The execution speed is quite slow (e.g., slower than AFL-QEMU)
+ The fuzzing process is stuck (i.e., the AFL panel does not have updates for a while)
+ StochFuzz crashes during rewriting
+ ...

## How to check whether an input will cause inconsistent behaviors.

As mentioned in [README.md](../README.md#basic-usage), after the initial rewriting, StochFuzz will generate a _phantom file_. Originally, if we want to do binary-only fuzzing, we attach AFL to this phantom binary. 

Actually, this phantom binary can also be directly executed, with the same arguments as the original binary has. 

Hence, to check whether an input will cause inconsistent behaviors, you can execute both the original binary and the phantom binary with the given input and check the behaviors of two binaries.

## Incorrect rewriting options or latent bugs in StochFuzz?

StochFuzz provides different rewriting options and will automatically choose some, based on the given binary. In some cases, StochFuzz may pick the wrong choices. The following steps can help us identify whether the erroneous behaviors are caused by incorrect rewriting options or latent bugs in StochFuzz.

+ First of all, make sure all the cached files are removed (`rm .*`) and try to rerun StochFuzz.
+ If the erroneous behaviors still exist but you have adopted the advanced strategy, please remove all cached files (`rm .*`) and try the basic mode.
+ If the erroneous behaviors still exist after adopting the basic mode, please remove all cached files (`rm .*`) and feed `-e -f -i` options into StochFuzz.

```
  -e            - install the fork server at the entrypoint instead of the main function
  -f            - forcedly assume there is data interleaving with code
  -i            - ignore the call-fallthrough edges to defense RET-misusing obfuscation
```

+ If the erroneous behaviors still exist after rewriting with the aforementioned options, please kindly open an issue to let us know; if the erroneous behaviors are gone, you can try aforementioned options one by one to identify which one contributes to elimilate the errors, and if possible, you can also open an issue to let us know. 


## Known issues

+ Like [AFL](https://github.com/google/AFL/blob/fab1ca5ed7e3552833a18fc2116d33a9241699bc/README.md#13-known-limitations--areas-for-improvement), StochFuzz cannot handle programs that install custom handlers for some important signals (SIGSEGV, SIGABRT, etc). Moreover, StochFuzz additionally occupies one more signal, _SIGUSR1_. If the subject program has a custom handler for SIGUSR1, the user may need to modify StochFuzz to use SIGUSR2 or other unused signals.


================================================
FILE: scripts/stochfuzz_env.sh
================================================
#!/bin/bash

stochfuzz_dir=$(realpath $(dirname "$(realpath $0)")/../)
libstochfuzzRT_path="$stochfuzz_dir/src/libstochfuzzRT.so"
libunwind_path="$stochfuzz_dir/libunwind/install/lib/libunwind.so"

if [ ! -f $libstochfuzzRT_path ]; then
    echo "libstochfuzzRT.so not found!"
    exit 1
fi

if [ ! -f $libunwind_path ]; then
    echo "libunwind.so not found!"
    exit 1
fi

export STOCHFUZZ_PRELOAD=$libstochfuzzRT_path:$libunwind_path
echo $STOCHFUZZ_PRELOAD


================================================
FILE: src/.clang-format
================================================
BasedOnStyle: Google
IndentWidth: 4
AlwaysBreakTemplateDeclarations: true
ColumnLimit: 80
UseTab: Never
AllowShortIfStatementsOnASingleLine: false
AllowShortBlocksOnASingleLine: false
AllowShortLoopsOnASingleLine: false


================================================
FILE: src/Makefile
================================================
CC = clang

SIGSTKSZ =  $(shell ./get_signal_stack_size.sh)
CFLAGS = -Wall -Wno-unused-command-line-argument -Wno-void-pointer-to-int-cast -Wno-void-pointer-to-enum-cast -fPIC -pie -ffast-math -D_GNU_SOURCE -DSIGNAL_STACK_SIZE=$(SIGSTKSZ)
LDFLAGS =

SHELLCODE_CFLAGS = -Wall -fno-stack-protector -fno-jump-tables -fpie -O3 -D_GNU_SOURCE -DSIGNAL_STACK_SIZE=$(SIGSTKSZ)

LIBNAME = $(shell find . -regex './lib[^\.\/]*\.h' | tr -d '/' | cut -d '.' -f2)
TOOLNAME = $(shell grep '^\#define OURTOOL ' config.h | cut -d '"' -f2)
VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2)

ifeq ($(shell ../test/check_avx512 2>/dev/null; echo $$?), 0)
	AVX_CFLAGS = -mavx512f -DAVX512
else
	AVX_CFLAGS =
endif

ifneq ($(origin DEBUG_REWRITER), undefined)
	CFLAGS += -DBINARY_SEARCH_INVALID_CRASH -DBINARY_SEARCH_DEBUG_REWRITER=$(strip $(DEBUG_REWRITER))
	SHELLCODE_CFLAGS += -DBINARY_SEARCH_INVALID_CRASH -DBINARY_SEARCH_DEBUG_REWRITER=$(strip $(DEBUG_REWRITER))
endif

# note that the new SINGLE_SUCC_OPT is not well test, as such we add an option to disable it
ifneq ($(origin SINGLE_SUCC_OPT), undefined)
ifeq ('$(SINGLE_SUCC_OPT)', 'disable')
	CFLAGS += -DNSINGLE_SUCC_OPT
	SHELLCODE_CFLAGS += -DNSINGLE_SUCC_OPT
endif
endif

ifneq ($(origin CONSERVATIVE_PATCH), undefined)
ifeq ('$(CONSERVATIVE_PATCH)', 'enable')
	CFLAGS += -DCONSERVATIVE_PATCH
	SHELLCODE_CFLAGS += -DCONSERVATIVE_PATCH
endif
endif

# glib
CFLAGS += $(shell PKG_CONFIG_PATH=$(realpath ..)/glib/lib/x86_64-linux-gnu/pkgconfig/ pkg-config --cflags glib-2.0)
LDFLAGS += -lpthread

# keystone
CFLAGS += -I $(realpath ..)/keystone/include
LDFLAGS += -lstdc++ -lm

# capstone
CFLAGS += -I $(realpath ..)/capstone/include
LDFLAGS +=

# libunwind
LIBUNWIND_RT_STEP_OFFSET = 0x$(shell readelf -s $(realpath ..)/libunwind/install/lib/libunwind.so  | grep _ULx86_64_step | head -n 1 | awk '{print $$2}')
LIBUNWIND_RT_CFLAGS += -fPIC -shared -I $(realpath ..)/libunwind/install/include -DSTEP_OFFSET=$(LIBUNWIND_RT_STEP_OFFSET) -DSIGNAL_STACK_SIZE=$(SIGSTKSZ)

OBJS=\
	binary.o \
	buffer.o \
	elf_.o \
	utils.o \
	interval_splay.o \
	mem_file.o \
	restricted_ptr.o \
	tp_dispatcher.o \
	sys_optarg.o \
	disassembler.o \
	rewriter.o \
	patcher.o \
	ucfg_analyzer.o \
	capstone_.o \
	diagnoser.o \
	library_functions/library_functions.o \
	core.o

.PHONY: clean format

libstochfuzzRT:
	gcc $(LIBUNWIND_RT_CFLAGS) -o libstochfuzzRT.so libstochfuzzRT.c

debug: CFLAGS += -g -O0 -fsanitize=address -fno-omit-frame-pointer -DDEBUG
debug: SHELLCODE_CFLAGS += -DDEBUG
debug: executable

profile: CFLAGS += -pg -O2 -DNDEBUG
profile: SHELLCODE_CFLAGS += -DNDEBUG
profile: executable

release: CFLAGS += -O2 -DNDEBUG
release: SHELLCODE_CFLAGS += -DNDEBUG
release: executable

executable: loader fork_server tps handlers library_functions_load libstochfuzzRT $(OBJS)
	ar rcs $(LIBNAME).a $(OBJS)
	$(CC) $(CFLAGS) $(LDFLAGS) -shared $(OBJS) $(realpath ..)/glib/lib/x86_64-linux-gnu/libglib-2.0.a $(realpath ..)/keystone/build/llvm/lib/libkeystone.a $(realpath ..)/capstone/libcapstone.a -o $(LIBNAME).so
	$(CC) $(CFLAGS) $(LDFLAGS) frontend.c $(LIBNAME).a $(realpath ..)/glib/lib/x86_64-linux-gnu/libglib-2.0.a $(realpath ..)/keystone/build/llvm/lib/libkeystone.a $(realpath ..)/capstone/libcapstone.a -o $(TOOLNAME)

loader:
	$(CC) $(SHELLCODE_CFLAGS) -c loader.c
	$(CC) -nostdlib -o loader.out loader.o -Wl,--entry=_entry
	objcopy --dump-section .text=loader.bin loader.out
	xxd -i loader.bin > loader_bin.c

fork_server:
	$(CC) $(SHELLCODE_CFLAGS) $(AVX_CFLAGS) -c fork_server.c
	$(CC) -nostdlib -o fork_server.out fork_server.o -Wl,--entry=_entry
	objcopy --dump-section .text=fork_server.bin fork_server.out
	xxd -i fork_server.bin > fork_server_bin.c

tps:
	$(MAKE) -C trampolines

handlers:
	python3 rewriter_handlers/generate.py rewriter_handlers

library_functions_load:
	python3 library_functions/generate.py lib.csv library_functions

ifeq ($(findstring -r,$(TEST_OPTIONS)), -r)
STOCHFUZZ_PRELOAD = $(shell ../scripts/stochfuzz_env.sh)
define test_succ
	cd test && ( STOCHFUZZ_PRELOAD=$(strip ${2}):$(STOCHFUZZ_PRELOAD) ${1} )
endef

define test_fail
	cd test && ( ! STOCHFUZZ_PRELOAD=$(strip ${2}):$(STOCHFUZZ_PRELOAD) ${1} )
endef

define test_whatever
	cd test && ( STOCHFUZZ_PRELOAD=$(strip ${2}):$(STOCHFUZZ_PRELOAD) ${1} || true )
endef
else
define test_succ
	cd test && ( ${1} )
endef

define test_fail
	cd test && ( ! ${1} )
endef

define test_whatever
	cd test && ( ${1} || true )
endef
endif

test:
	rm -rf test; cp -r ../test test
	$(call test_succ, ../$(TOOLNAME) -P $(TEST_OPTIONS) -- bzip2.no.pie)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- bzip2.no.pie --help)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- bzip2.no.pie -kfd test.c.bz2)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- bzip2.no.pie )
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- libpng-1.2.56 seed.png)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- libpng-1.2.56)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- json-2017-02-12.normal json.seed)
	$(call test_fail, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- crash mdzz)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- crash )
	$(call test_succ, ../$(TOOLNAME) -P $(TEST_OPTIONS) -- openssl-1.0.1f)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- openssl-1.0.1f leak-268f0e85f4bc45cbaf4d257222b830eac18977f3)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- openssl-1.0.1f)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- hello)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- hello)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- rar e -o+ -mt3 -- test.rar)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- rar)
	$(call test_fail, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- timeout mdzz)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- timeout)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- readelf.pie -a small_exec.elf)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- bzip2.pie -kfd test.c.bz2)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- pngfix.pie seed.png)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- pngfix.pie toucan.png)
ifneq ($(strip $(shell whereis libasan.so.4 | cut -d ' ' -f2- | xargs ls | grep 'libasan.so.4')),)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- libjpeg.asan seed.jpg, $(shell whereis libasan.so.4 | cut -d ' ' -f2- | xargs ls | grep 'libasan.so.4'))
endif
ifneq ($(findstring -n,$(TEST_OPTIONS)), -n)
	$(call test_whatever, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- unintentional_crash mdzz)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- unintentional_crash)
	$(call test_succ, ../$(TOOLNAME) -V $(TEST_OPTIONS) -- unintentional_crash)
endif
ifeq ($(findstring -e,$(TEST_OPTIONS)), -e)
	$(call test_fail, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- no_main mdzz)
	$(call test_succ, ../$(TOOLNAME) -R $(TEST_OPTIONS) -- no_main)
endif
ifneq ($(findstring -f,$(TEST_OPTIONS)), -f)
	$(call test_whatever, timeout --signal=KILL 10m ../$(TOOLNAME) -R -t 5000 $(TEST_OPTIONS) -- z3 -smt2 ex.smt2) # this test may fail due to the memory limit of Github Actions
endif
	# test daemon
	rm -rf test; cp -r ../test test
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' bzip2.no.pie -kfd test.c.bz2)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' libpng-1.2.56 seed.png)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' json-2017-02-12.normal json.seed)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' openssl-1.0.1f leak-268f0e85f4bc45cbaf4d257222b830eac18977f3)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' rar e -o+ -mt3 -- test.rar)
	$(call test_fail, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' crash mdzz)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' crash)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' readelf.pie -a small_exec.elf)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' bzip2.pie -kfd test.c.bz2)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' pngfix.pie seed.png)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' pngfix.pie toucan.png)
ifneq ($(strip $(shell whereis libasan.so.4 | cut -d ' ' -f2- | xargs ls | grep 'libasan.so.4')),)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' libjpeg.asan seed.jpg, $(shell whereis libasan.so.4 | cut -d ' ' -f2- | xargs ls | grep 'libasan.so.4'))
endif
ifeq ($(findstring -r,$(TEST_OPTIONS)), -r)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS) -e' hello)
else
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' hello)
endif
ifneq ($(findstring -n,$(TEST_OPTIONS)), -n)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' unintentional_crash mdzz)
endif
ifeq ($(findstring -e,$(TEST_OPTIONS)), -e)
	$(call test_succ, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' no_main mdzz)
endif
	$(call test_fail, ./test_daemon.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' timeout mdzz)
	$(call test_succ, cat timeout.daemon.log)
	$(call test_succ, grep -F 'get status code: 0x9 (signal: 9)' timeout.daemon.log)

GOOGLE_FTS=\
    boringssl-2016-02-12 \
    c-ares-CVE-2016-5180 \
    freetype2-2017 \
    guetzli-2017-3-30 \
    harfbuzz-1.3.2 \
    json-2017-02-12 \
    lcms-2017-03-21 \
    libarchive-2017-01-04 \
    libjpeg-turbo-07-2017 \
    libpng-1.2.56 \
    libssh-2017-1272 \
    libxml2-v2.9.2 \
    llvm-libcxxabi-2017-01-27 \
    openssl-1.0.1f \
    openssl-1.0.2d \
    openssl-1.1.0c \
    openthread-2018-02-27 \
    pcre2-10.00 \
    proj4-2017-08-14 \
    re2-2014-12-09 \
    sqlite-2016-11-14 \
    vorbis-2017-12-11 \
    woff2-2016-05-06 \
    wpantund-2018-02-27

prepare_google_fts:
	rm -rf test; cp -r ../benchmark test; cp ../test/test_daemon_ignore_asan_sof.sh test

$(GOOGLE_FTS): prepare_google_fts
	$(call test_succ, ./test_daemon_ignore_asan_sof.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' $@.normal $@.seed)
	$(call test_succ, ./test_daemon_ignore_asan_sof.sh ../$(TOOLNAME) '$(TEST_OPTIONS)' $@.inline $@.seed)
	$(call test_succ, rm -f .pdisasm.$@.normal .pdisasm.$@.inline)
	$(call test_succ, grep -F "SUMMARY: AddressSanitizer: stack-overflow" $@.normal.daemon.log || ../$(TOOLNAME) -R $(TEST_OPTIONS) -- $@.normal $@.seed || grep -F "we encounter a rewriting error" $@.normal.daemon.log)
	$(call test_succ, grep -F "SUMMARY: AddressSanitizer: stack-overflow" $@.inline.daemon.log || ../$(TOOLNAME) -R $(TEST_OPTIONS) -- $@.inline $@.seed || grep -F "we encounter a rewriting error" $@.inline.daemon.log)

benchmark: prepare_google_fts $(GOOGLE_FTS)

clean:
	rm -rf $(OBJS) *.out *.bin *.o *.a *.so *_bin.c $(TOOLNAME) test/ library_functions/library_functions_load.c rewriter_handlers/handler_main.c
	$(MAKE) -C trampolines clean

SOURCES:=$(OBJS:.o=.c)
HEADERS:=$(OBJS:.o=.h)
SOURCES += loader.c fork_server.c frontend.c asm_syscall.c asm_utils.c libstochfuzzRT.c
SOURCES += rewriter_handlers/*.c rewriter_handlers/*.in
SOURCES += prob_disasm/*.c
SOURCES += prob_disasm/prob_disasm_complete/*.c
HEADERS += address_dictionary.h loader.h fork_server.h config.h afl_config.h crs_config.h $(LIBNAME).h

format:
	clang-format -sort-includes -style=file -i $(SOURCES)
	clang-format -sort-includes -style=file -i $(HEADERS)
	$(MAKE) -C trampolines format


================================================
FILE: src/address_dictionary.h
================================================
/*
 * address_dictionary.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __ADDRESS_DICTIONARY_H
#define __ADDRESS_DICTIONARY_H

#include "config.h"
#include "utils.h"

// force evaluation
#define __ADDR_DICT_NAME_2(x, y) __AddrDict_##y##_##x##_t
#define __ADDR_DICT_NAME_1(x, y) __ADDR_DICT_NAME_2(x, y)
#define __ADDR_DICT_NAME(x) __ADDR_DICT_NAME_1(x, __COUNTER__)

/*
 * Address dictionary uses a contiguous memory to store data, and uses key as
 * index to access. Compared with GHashTable, it is a much more efficient
 * approach to build a hash table who uses address as key and is likely to use
 * all addresses.
 *
 * Note that we use macro to simulate template in C++.
 */
#define AddrDict(type, name)        \
    struct __ADDR_DICT_NAME(name) { \
        type *__data;               \
        uint64_t *__used;           \
        addr_t __base;              \
        size_t __size;              \
    } name

/*
 * AddrDict without checking existence.
 * It is very helpful for hash tables whose value cannot be zero.
 */
#define AddrDictFast(type, name)    \
    struct __ADDR_DICT_NAME(name) { \
        type *__data;               \
        PhantomType *__used;        \
        addr_t __base;              \
        size_t __size;              \
    } name

#define z_addr_dict_init(dict, base_addr, size)                                \
    do {                                                                       \
        (dict).__base = (base_addr);                                           \
        (dict).__size = (size);                                                \
        (dict).__data = z_alloc((dict).__size, sizeof(*((dict).__data)));      \
        if (_Generic(((dict).__used), PhantomType *                            \
                     : false, default                                          \
                     : true)) {                                                \
            (dict).__used = z_alloc((dict).__size / 64 + 1, sizeof(uint64_t)); \
        } else {                                                               \
            (dict).__used = NULL;                                              \
        }                                                                      \
    } while (0)

#define z_addr_dict_check_addr(dict, addr)                         \
    do {                                                           \
        if ((addr) < (dict).__base ||                              \
            (addr) >= (dict).__base + (dict).__size) {             \
            EXITME("out-of-boundry access in address dictionary"); \
        }                                                          \
    } while (0)

#define z_addr_dict_exist(dict, addr)                         \
    ({                                                        \
        bool res;                                             \
        z_addr_dict_check_addr(dict, addr);                   \
                                                              \
        size_t __off = (addr) - (dict).__base;                \
                                                              \
        if (_Generic(((dict).__used), PhantomType *           \
                     : false, default                         \
                     : true)) {                               \
            size_t __off_div = __off / 64;                    \
            size_t __off_mod = __off % 64;                    \
            uint64_t *__bits = (uint64_t *)((dict).__used);   \
            res = !!(__bits[__off_div] & (1UL << __off_mod)); \
        } else {                                              \
            res = !!((dict).__data[__off]);                   \
        }                                                     \
                                                              \
        res;                                                  \
    })

#define z_addr_dict_set(dict, addr, val)                    \
    do {                                                    \
        z_addr_dict_check_addr(dict, addr);                 \
                                                            \
        size_t __off = (addr) - (dict).__base;              \
        (dict).__data[__off] = (val);                       \
                                                            \
        if ((dict).__used) {                                \
            size_t __off_div = __off / 64;                  \
            size_t __off_mod = __off % 64;                  \
            uint64_t *__bits = (uint64_t *)((dict).__used); \
            __bits[__off_div] |= (1UL << __off_mod);        \
        }                                                   \
    } while (0)

#define z_addr_dict_get(dict, addr)                               \
    ({                                                            \
        z_addr_dict_check_addr(dict, addr);                       \
        if (!z_addr_dict_exist(dict, addr)) {                     \
            EXITME("uninitialized access in address dictionary"); \
        }                                                         \
        (dict).__data[(addr) - (dict).__base];                    \
    })

#define z_addr_dict_get_data(dict) ((dict).__data)
#define z_addr_dict_get_base(dict) ((dict).__base)
#define z_addr_dict_get_size(dict) ((dict).__size)

#define z_addr_dict_remove(dict, addr)                      \
    do {                                                    \
        z_addr_dict_check_addr(dict, addr);                 \
        size_t __off = (addr) - (dict).__base;              \
        (dict).__data[__off] = 0;                           \
                                                            \
        if ((dict).__used) {                                \
            size_t __off_div = __off / 64;                  \
            size_t __off_mod = __off % 64;                  \
            uint64_t *__bits = (uint64_t *)((dict).__used); \
            __bits[__off_div] &= (~(1UL << __off_mod));     \
        }                                                   \
    } while (0)

/*
 * z_addr_dist_destroy should support variable numbers of arguments
 */
#define __addr_dict_destroy_opt_0(...)
#define __addr_dict_destroy_opt_1(...)
#define __addr_dict_destroy_opt_2(dict, func)              \
    do {                                                   \
        for (size_t __i = 0; __i < (dict).__size; __i++) { \
            addr_t __addr = (dict).__base + __i;           \
            if (z_addr_dict_exist(dict, __addr)) {         \
                (*(func))((dict).__data[__i]);             \
            }                                              \
        }                                                  \
    } while (0)

#define __addr_dict_destroy_choose(a, b, c, f, ...) f

#define __addr_dict_destroy_data(...)                                  \
    __addr_dict_destroy_choose(, ##__VA_ARGS__,                        \
                               __addr_dict_destroy_opt_2(__VA_ARGS__), \
                               __addr_dict_destroy_opt_1(__VA_ARGS__), \
                               __addr_dict_destroy_opt_0(__VA_ARGS__))

#define __addr_dict_destroy_self(dict, ...) \
    do {                                    \
        z_free((dict).__data);              \
        z_free((dict).__used);              \
    } while (0)

#define z_addr_dict_destroy(...)               \
    do {                                       \
        __addr_dict_destroy_data(__VA_ARGS__); \
        __addr_dict_destroy_self(__VA_ARGS__); \
    } while (0)

#endif


================================================
FILE: src/afl_config.h
================================================
/*
 * afl_config.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __AFL_CONFIG_H
#define __AFL_CONFIG_H

#include "config.h"

/*
 * XXX: Attaching SHM at a fixed address allows around 10% perf gain. see
 * https://github.com/google/AFL/blob/master/afl-as.h#L71.
 *
 * Note that it is reasonable for a binary-instrumented tool to fix the address,
 * as we can know the memory layout comparied with from assemble view.
 *
 */
/*
 * TODO: when rewritting, dynamically calculate the fixed AFL_MAP_ADDR.
 */
#define AFL_FORKSRV_FD 198
#define AFL_SHM_ENV "__AFL_SHM_ID"
#define AFL_MAP_SIZE_POW2 16
#define AFL_MAP_SIZE (1 << AFL_MAP_SIZE_POW2)
#define AFL_MAP_ADDR (RW_PAGE_ADDR + 0x10000)
#define AFL_PREV_ID_PTR (RW_PAGE_ADDR + 0x8)
#define AFL_MAP_SIZE_MASK ((1 << AFL_MAP_SIZE_POW2) - 1)

// #define AFL_BB_ID(x) ((((x) >> 4) ^ ((x) << 8)) & AFL_MAP_SIZE_MASK)
// AFL_BB_ID Algorithm used in AFL-QEMU, but it seems bad on static binary
// rewriting

#define AFL_BB_ID(x) (((x) ^ ((x) >> AFL_MAP_SIZE_POW2)) & AFL_MAP_SIZE_MASK)

#define AFL_HASH_CONST 0xa5b35705

#endif


================================================
FILE: src/asm_syscall.c
================================================
/*
 * asm_syscall.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define NO_INLINE __attribute__((__noinline__))
#define NO_RETURN __attribute__((__noreturn__))

#define Z_SYSCALL __attribute__((unused)) static inline

#define ASM_STRING(name, content)       \
    ".global " #name                    \
    "\n"                                \
    ".type " #name ",@function\n" #name \
    ":\n"                               \
    ".ascii \"" content                 \
    "\"\n"                              \
    ".byte 0x00\n"

/*
 * Kernal sigaction (unlike glibc wrapper)
 */
struct kernel_sigaction {
    void (*k_sa_handler)(int, siginfo_t *, void *);
    unsigned long sa_flags;
    void (*sa_restorer)(void);
    unsigned long sa_mask;
};

Z_SYSCALL unsigned long sys_prctl(unsigned long option_0, unsigned long arg2_0,
                                  unsigned long arg3_0, unsigned long arg4_0,
                                  unsigned long arg5_0) {
    register uintptr_t option asm("rdi") = (uintptr_t)option_0;
    register uintptr_t arg2 asm("rsi") = (uintptr_t)arg2_0;
    register uintptr_t arg3 asm("rdx") = (uintptr_t)arg3_0;
    register uintptr_t arg4 asm("r10") = (uintptr_t)arg4_0;
    register uintptr_t arg5 asm("r8") = (uintptr_t)arg5_0;
    register uintptr_t err asm("rax");

    asm volatile(
        "mov $157, %%eax\n\t"  // SYS_PRCTL
        "syscall"
        : "=rax"(err)
        : "r"(option), "r"(arg2), "r"(arg3), "r"(arg4), "r"(arg5)
        : "rcx", "r11");

    return (unsigned long)err;
}

Z_SYSCALL unsigned long sys_clone(unsigned long clone_flags_0,
                                  unsigned long newsp_0, pid_t *parent_tidptr_0,
                                  pid_t *child_tidptr_0, void *tls_val_0) {
    register uintptr_t clone_flags asm("rdi") = (uintptr_t)clone_flags_0;
    register uintptr_t newsp asm("rsi") = (uintptr_t)newsp_0;
    register uintptr_t parent_tidptr asm("rdx") = (uintptr_t)parent_tidptr_0;
    register uintptr_t child_tidptr asm("r10") = (uintptr_t)child_tidptr_0;
    register uintptr_t tls_val asm("r8") = (uintptr_t)tls_val_0;
    register uintptr_t err asm("rax");

    asm volatile(
        "mov $56, %%eax\n\t"  // SYS_CLONE
        "syscall"
        : "=rax"(err)
        : "r"(clone_flags), "r"(newsp), "r"(parent_tidptr), "r"(child_tidptr),
          "r"(tls_val)
        : "rcx", "r11");

    return (unsigned long)err;
}

Z_SYSCALL unsigned long sys_mmap(unsigned long addr_0, unsigned long len_0,
                                 unsigned long prot_0, unsigned long flags_0,
                                 unsigned long fd_0, unsigned long off_0) {
    register uintptr_t addr asm("rdi") = (uintptr_t)addr_0;
    register uintptr_t len asm("rsi") = (uintptr_t)len_0;
    register uintptr_t prot asm("rdx") = (uintptr_t)prot_0;
    register uintptr_t flags asm("r10") = (uintptr_t)flags_0;
    register uintptr_t fd asm("r8") = (uintptr_t)fd_0;
    register uintptr_t off asm("r9") = (uintptr_t)off_0;
    register uintptr_t err asm("rax");

    asm volatile(
        "mov $9, %%eax\n\t"  // SYS_MMAP
        "syscall"
        : "=rax"(err)
        : "r"(addr), "r"(len), "r"(prot), "r"(flags), "r"(fd), "r"(off)
        : "rcx", "r11");

    return (unsigned long)err;
}

Z_SYSCALL int sys_mprotect(unsigned long start_0, size_t len_0,
                           unsigned long prot_0) {
    register uintptr_t start asm("rdi") = (uintptr_t)start_0;
    register uintptr_t len asm("rsi") = (uintptr_t)len_0;
    register uintptr_t prot asm("rdx") = (uintptr_t)prot_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $10, %%eax\n\t"  // SYS_MPROTECT
        "syscall"
        : "=rax"(err)
        : "r"(start), "r"(len), "r"(prot)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_open(const char *filename_0, int flags_0, int mode_0) {
    register uintptr_t filename asm("rdi") = (uintptr_t)filename_0;
    register uintptr_t flags asm("rsi") = (uintptr_t)flags_0;
    register uintptr_t mode asm("rdx") = (uintptr_t)mode_0;
    register intptr_t fd asm("rax");

    asm volatile(
        "mov $2, %%eax\n\t"  // SYS_OPEN
        "syscall"
        : "=rax"(fd)
        : "r"(filename), "r"(flags), "r"(mode)
        : "rcx", "r11");

    return (int)fd;
}

Z_SYSCALL int sys_pipe(int *pipefd_0) {
    register uintptr_t pipefd asm("rdi") = (uintptr_t)pipefd_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $22, %%eax\n\t"  // SYS_PIPE
        "syscall"
        : "=rax"(err)
        : "r"(pipefd)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_close(int fd_0) {
    register uintptr_t fd asm("rdi") = (uintptr_t)fd_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $3, %%eax\n\t"  // SYS_CLOSE
        "syscall"
        : "=rax"(err)
        : "r"(fd)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_rt_sigaction(int sig_0, struct kernel_sigaction *act_0,
                               struct kernel_sigaction *oact_0,
                               size_t sigsetsize_0) {
    register uintptr_t sig asm("rdi") = (uintptr_t)sig_0;
    register uintptr_t act asm("rsi") = (uintptr_t)act_0;
    register uintptr_t oact asm("rdx") = (uintptr_t)oact_0;
    register uintptr_t sigsetsize asm("r10") = (uintptr_t)sigsetsize_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $13, %%eax\n\t"  // SYS_RT_SIGACTION
        "syscall"
        : "=rax"(err)
        : "r"(sig), "r"(act), "r"(oact), "r"(sigsetsize)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_connect(int fd_0, struct sockaddr *addr_0, int addrlen_0) {
    register uintptr_t fd asm("rdi") = (uintptr_t)fd_0;
    register uintptr_t addr asm("rsi") = (uintptr_t)addr_0;
    register uintptr_t addrlen asm("rdx") = (uintptr_t)addrlen_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $42, %%eax\n\t"  // SYS_CONNECT
        "syscall"
        : "=rax"(err)
        : "r"(fd), "r"(addr), "r"(addrlen)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_socket(int family_0, int type_0, int protocol_0) {
    register uintptr_t family asm("rdi") = (uintptr_t)family_0;
    register uintptr_t type asm("rsi") = (uintptr_t)type_0;
    register uintptr_t protocol asm("rdx") = (uintptr_t)protocol_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $41, %%eax\n\t"  // SYS_SOCKET
        "syscall"
        : "=rax"(err)
        : "r"(family), "r"(type), "r"(protocol)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_write(int fd_0, const char *buf_0, size_t len_0) {
    register uintptr_t fd asm("rdi") = (uintptr_t)fd_0;
    register uintptr_t buf asm("rsi") = (uintptr_t)buf_0;
    register uintptr_t len asm("rdx") = (uintptr_t)len_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $1, %%eax\n\t"  // SYS_WRITE
        "syscall"
        : "=rax"(err)
        : "r"(fd), "r"(buf), "r"(len)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_sigaltstack(stack_t *uss_0, stack_t *uoss_0) {
    register uintptr_t uss asm("rdi") = (uintptr_t)uss_0;
    register uintptr_t uoss asm("rsi") = (uintptr_t)uoss_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $131, %%eax\n\t"  // SYS_SIGALTSTACK
        "syscall"
        : "=rax"(err)
        : "r"(uss), "r"(uoss)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_dup2(int oldfd_0, int newfd_0) {
    register uintptr_t oldfd asm("rdi") = (uintptr_t)oldfd_0;
    register uintptr_t newfd asm("rsi") = (uintptr_t)newfd_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $33, %%eax\n\t"  // SYS_DUP2
        "syscall"
        : "=rax"(err)
        : "r"(oldfd), "r"(newfd)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_fstat(unsigned int fd_0, struct stat *buf_0) {
    register uintptr_t fd asm("rdi") = (uintptr_t)fd_0;
    register uintptr_t buf asm("rsi") = (uintptr_t)buf_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $5, %%eax\n\t"  // SYS_FSTAT
        "syscall"
        : "=rax"(err)
        : "r"(fd), "r"(buf)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_exit(int error_code_0) {
    register uintptr_t error_code asm("rdi") = (uintptr_t)error_code_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $60, %%eax\n\t"  // SYS_EXIT
        "syscall"
        : "=rax"(err)
        : "r"(error_code)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_kill(pid_t pid_0, int sig_0) {
    register uintptr_t pid asm("rdi") = (uintptr_t)pid_0;
    register uintptr_t sig asm("rsi") = (uintptr_t)sig_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $62, %%eax\n\t"  // SYS_KILL
        "syscall"
        : "=rax"(err)
        : "r"(pid), "r"(sig)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_msync(unsigned long start_0, size_t len_0, int flags_0) {
    register uintptr_t start asm("rdi") = (uintptr_t)start_0;
    register uintptr_t len asm("rsi") = (uintptr_t)len_0;
    register uintptr_t flags asm("rdx") = (uintptr_t)flags_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $26, %%eax\n\t"  // SYS_MSYNC
        "syscall"
        : "=rax"(err)
        : "r"(start), "r"(len), "r"(flags)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_read(int fd_0, const char *buf_0, size_t len_0) {
    register uintptr_t fd asm("rdi") = (uintptr_t)fd_0;
    register uintptr_t buf asm("rsi") = (uintptr_t)buf_0;
    register uintptr_t len asm("rdx") = (uintptr_t)len_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $0, %%eax\n\t"  // SYS_READ
        "syscall"
        : "=rax"(err)
        : "r"(fd), "r"(buf), "r"(len)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL pid_t sys_wait4(pid_t pid_0, int *wstatus_0, int options_0,
                          struct rusage *rusage_0) {
    register uintptr_t pid asm("rdi") = (uintptr_t)pid_0;
    register uintptr_t wstatus asm("rsi") = (uintptr_t)wstatus_0;
    register uintptr_t options asm("rdx") = (uintptr_t)options_0;
    register uintptr_t rusage asm("r10") = (uintptr_t)rusage_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $61, %%eax\n\t"  // SYS_WAIT4
        "syscall"
        : "=rax"(err)
        : "r"(pid), "r"(wstatus), "r"(options), "r"(rusage)
        : "rcx", "r11");

    return (pid_t)err;
}

Z_SYSCALL void *sys_shmat(int shmid_0, const void *shmaddr_0, int shmflg_0) {
    register uintptr_t shmid asm("rdi") = (uintptr_t)shmid_0;
    register uintptr_t shmaddr asm("rsi") = (uintptr_t)shmaddr_0;
    register uintptr_t shmflg asm("rdx") = (uintptr_t)shmflg_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $30, %%eax\n\t"  // SYS_SHMAT
        "syscall"
        : "=rax"(err)
        : "r"(shmid), "r"(shmaddr), "r"(shmflg)
        : "rcx", "r11");

    return (void *)err;
}

Z_SYSCALL pid_t sys_getpid() {
    register intptr_t err asm("rax");

    asm volatile(
        "mov $39, %%eax\n\t"  // SYS_GETPID
        "syscall"
        : "=rax"(err)
        :
        : "rcx", "r11");

    return (pid_t)err;
}

Z_SYSCALL pid_t sys_fork() {
    register intptr_t err asm("rax");

    asm volatile(
        "mov $57, %%eax\n\t"  // SYS_FORK
        "syscall"
        : "=rax"(err)
        :
        : "rcx", "r11");

    return (pid_t)err;
}

Z_SYSCALL pid_t sys_pause() {
    register intptr_t err asm("rax");

    asm volatile(
        "mov $34, %%eax\n\t"  // SYS_PAUSE
        "syscall"
        : "=rax"(err)
        :
        : "rcx", "r11");

    return (pid_t)err;
}

Z_SYSCALL int sys_setpgid(pid_t pid_0, pid_t pgid_0) {
    register uintptr_t pid asm("rdi") = (uintptr_t)pid_0;
    register uintptr_t pgid asm("rsi") = (uintptr_t)pgid_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $109, %%eax\n\t"  // SYS_SETPGID
        "syscall"
        : "=rax"(err)
        : "r"(pid), "r"(pgid)
        : "rcx", "r11");

    return (int)err;
}

Z_SYSCALL int sys_munmap(unsigned long addr_0, size_t len_0) {
    register uintptr_t addr asm("rdi") = (uintptr_t)addr_0;
    register uintptr_t len asm("rsi") = (uintptr_t)len_0;
    register intptr_t err asm("rax");

    asm volatile(
        "mov $11, %%eax\n\t"  // SYS_MUNMAP
        "syscall"
        : "=rax"(err)
        : "r"(addr), "r"(len)
        : "rcx", "r11");

    return (int)err;
}


================================================
FILE: src/asm_utils.c
================================================
/*
 * asm_utils.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <fcntl.h>

#include "asm_syscall.c"

#define Z_UTILS __attribute__((unused)) static inline

#ifdef DEBUG
#define utils_puts(s, b) __utils_puts(s, b)
#define utils_error(s, e) __utils_error(s, e)
#else
#define utils_puts(s, b)
#define utils_error(s, e)                 \
    do {                                  \
        if (e) {                          \
            sys_kill(/*pid=*/0, SIGKILL); \
            asm volatile("ud2");          \
            __builtin_unreachable();      \
        }                                 \
    } while (0)
#endif

#define utils_likely(x) __builtin_expect(!!(x), 1)
#define utils_unlikely(x) __builtin_expect(!!(x), 0)

Z_UTILS void __utils_puts(const char *s, bool newline) {
    const char *buf = s;
    const char *cur = s;
    for (; *cur != '\0'; cur++)
        ;
    sys_write(STDERR_FILENO, buf, cur - buf);

    if (newline) {
        const char newline = '\n';
        sys_write(STDERR_FILENO, &newline, 1);
    }
}

Z_UTILS void utils_num2hexstr(char *s, uint64_t n) {
    uint64_t r = 0x1000000000000000;
    while (r != 0) {
        char c = n / r;
        if (c < 10) {
            *(s++) = '0' + c;
        } else {
            *(s++) = 'a' + c - 10;
        }
        n %= r;
        r /= 0x10;
    }
}

Z_UTILS unsigned long utils_hexstr2num(const char **str_ptr) {
    const char *str = *str_ptr;
    unsigned long x = 0;
    while (true) {
        char c = *str++;
        if (c >= '0' && c <= '9') {
            x <<= 4;
            x |= (unsigned long)(c - '0');
        } else if (c >= 'a' && c <= 'f') {
            x <<= 4;
            x |= (unsigned long)(10 + c - 'a');
        } else {
            *str_ptr = str;
            return x;
        }
    }
}

Z_UTILS void utils_output_number(uint64_t n) {
    char *s = (char *)(RW_PAGE_ADDR + RW_PAGE_USED_SIZE + 0x50);
    *(s + 16) = '\x00';
    utils_num2hexstr(s, n);
    utils_puts(s, true);
}

Z_UTILS void __utils_error(const char *err_str, bool need_exit) {
    utils_puts(err_str, true);
    if (need_exit) {
        asm volatile("int3");
        __builtin_unreachable();
    }
}

Z_UTILS size_t utils_strcpy(char *dst, char *src) {
    for (size_t i = 0;; i++) {
        dst[i] = src[i];
        if (!src[i]) {
            return i;
        }
    }
}

/*
 * Load external file.
 */
Z_UTILS size_t utils_mmap_external_file(const char *filename, bool remmap,
                                        unsigned long addr, int prot) {
    // Step (0): prepare error string
#ifdef DEBUG
    char s_[16];
    s_[0] = 'm';
    s_[1] = 'm';
    s_[2] = 'a';
    s_[3] = 'p';
    s_[4] = ' ';
    s_[5] = 'f';
    s_[6] = 'a';
    s_[7] = 'i';
    s_[8] = 'l';
    s_[9] = 'e';
    s_[10] = 'd';
    s_[11] = '\n';
    s_[12] = '\x00';
    s_[13] = ' ';
    s_[14] = '\x00';
#endif

    // Step (1): open file
    int fd = sys_open(filename, (prot & PROT_WRITE) ? O_RDWR : O_RDONLY, 0);
    if (fd < 0) {
        utils_puts(filename, false);
        utils_puts(s_ + 13, false);
        utils_error(s_, true);
    }

    // Step (2): get file size
    struct stat buf = {};
    if (sys_fstat(fd, &buf)) {
        utils_error(s_, true);
    }
    size_t fd_size = buf.st_size;
    if (fd_size != (fd_size >> PAGE_SIZE_POW2) << PAGE_SIZE_POW2) {
        char s[0x20] = "";
        utils_num2hexstr(s, fd_size);
        utils_puts(s, false);
        utils_error(s_, true);
    }

    // Step (3). remmap if needed
    if (remmap) {
        if (sys_munmap(addr, fd_size)) {
            utils_error(s_, true);
        }
    }

    // Step (4): mmap file
#ifdef BINARY_SEARCH_INVALID_CRASH
    // make gdb able to set breakpoints at mmapped pages
    if (sys_mmap(addr, fd_size, prot, MAP_PRIVATE | MAP_FIXED, fd, 0) != addr) {
#else
    if (sys_mmap(addr, fd_size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != addr) {
#endif
        utils_error(s_, true);
    }
    if (sys_close(fd)) {
        utils_error(s_, true);
    }

    return fd_size;
}


================================================
FILE: src/binary.c
================================================
/*
 * binary.c
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "binary.h"
#include "elf_.h"
#include "fork_server.h"
#include "interval_splay.h"
#include "loader.h"
#include "utils.h"

#include "x64_utils.c"

#include "fork_server_bin.c"
#include "loader_bin.c"

#define BINARY_MMAP_EXIST(b, addr)                                          \
    (g_hash_table_lookup(b->mmapped_pages, GSIZE_TO_POINTER(addr)) == NULL) \
        ? false                                                             \
        : true

#define BINARY_MMAP_INSERT(b, addr)                               \
    g_hash_table_insert(b->mmapped_pages, GSIZE_TO_POINTER(addr), \
                        GINT_TO_POINTER(1))

static const char null_buf[0x30] = {0};

/*
 * Align trampolines_addr
 */
Z_PRIVATE void __binary_align_trampolines_addr(Binary *b);

/*
 * Setup basic information for loader
 */
Z_PRIVATE void __binary_setup_loader(Binary *b);

/*
 * Setup lookup table
 */
Z_PRIVATE void __binary_setup_lookup_table(Binary *b);

/*
 * Setup retaddr mapping
 */
Z_PRIVATE void __binary_setup_retaddr_mapping(Binary *b);

/*
 * Setup fork server
 */
Z_PRIVATE void __binary_setup_fork_server(Binary *b);

/*
 * Setup trampoline zone
 */
Z_PRIVATE void __binary_setup_tp_zone(Binary *b);

/*
 * Setter and Getter
 */
DEFINE_GETTER(Binary, binary, ELF *, elf);
DEFINE_GETTER(Binary, binary, const char *, original_filename);
DEFINE_GETTER(Binary, binary, addr_t, trampolines_addr);
DEFINE_GETTER(Binary, binary, addr_t, shadow_main);
OVERLOAD_GETTER(Binary, binary, addr_t, shadow_code_addr) {
    return binary->trampolines_addr;
}

OVERLOAD_SETTER(Binary, binary, addr_t, shadow_start) {
    z_info("shadow _start address: %#lx", shadow_start);
    binary->shadow_start = shadow_start;

    if (binary->prior_fork_server) {
        // when -e option is given, we need to change the fork server to _start
        addr_t gadget_addr = binary->fork_server_addr + fork_server_bin_len;
        KS_ASM_JMP(gadget_addr, shadow_start);
        z_elf_write(binary->elf, gadget_addr, ks_size, ks_encode);
    } else {
        addr_t gadget_addr = binary->loader_addr + loader_bin_len;
        KS_ASM_JMP(gadget_addr, shadow_start);
        z_elf_write(binary->elf, gadget_addr, ks_size, ks_encode);
    }
}

OVERLOAD_SETTER(Binary, binary, addr_t, shadow_main) {
    if (binary->prior_fork_server) {
        EXITME("main function has not been detected");
    }

    z_info("shadow main address: %#lx", shadow_main);
    binary->shadow_main = shadow_main;
    addr_t gadget_addr = binary->fork_server_addr + fork_server_bin_len;
    KS_ASM_JMP(gadget_addr, shadow_main);
    z_elf_write(binary->elf, gadget_addr, ks_size, ks_encode);
}

OVERLOAD_SETTER(Binary, binary, ELFState, elf_state) {
    z_elf_set_state(binary->elf, elf_state);
}

Z_PRIVATE void __binary_align_trampolines_addr(Binary *b) {
    b->trampolines_addr = BITS_ALIGN_CELL(b->trampolines_addr, 3);
}

Z_PRIVATE void __binary_setup_loader(Binary *b) {
    // step (0). create basic data struction
    b->mmapped_pages =
        g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);

    // current address for setting instruction
    addr_t loader_base = z_elf_get_loader_addr(b->elf);
    b->loader_addr = loader_base;
    addr_t cur_addr = loader_base;

    // step (1). set entrypoint to loader address
    z_elf_get_ehdr(b->elf)->e_entry = cur_addr;

    // step (2). set down loader
    z_elf_write(b->elf, cur_addr, loader_bin_len, loader_bin);
    cur_addr += loader_bin_len;

    // step (3). jump to original entrypoint
    addr_t loader_transfer_jmp_addr = cur_addr;
    KS_ASM_JMP(cur_addr, z_elf_get_ori_entry(b->elf));
    assert(ks_size == 5);
    z_elf_write(b->elf, cur_addr, ks_size, ks_encode);
    cur_addr += ks_size;

    // step (4). 8-byte alignment for following data
    cur_addr = BITS_ALIGN_CELL(cur_addr, 3);

    // step (5). set down loader_base
    z_elf_write(b->elf, cur_addr, sizeof(addr_t), &loader_base);
    cur_addr += sizeof(addr_t);

    // step (6). set down tp_addr
    // XXX: we will first set a NULL trampoline at trapoline zone
    addr_t trampolines_addr = z_elf_get_trampolines_addr(b->elf);
    assert(trampolines_addr % PAGE_SIZE == 0);
    z_elf_write(b->elf, cur_addr, sizeof(addr_t), &(trampolines_addr));
    cur_addr += sizeof(addr_t);

    // step (7). set down shared .text base address
    addr_t shared_text_addr = z_elf_get_shared_text_addr(b->elf);
    assert(shared_text_addr % PAGE_SIZE == 0);
    z_elf_write(b->elf, cur_addr, sizeof(addr_t), &(shared_text_addr));
    cur_addr += sizeof(addr_t);

    // step (8). store trampolines name
    const char *trampolines_name = z_elf_get_trampolines_name(b->elf);
    z_elf_write(b->elf, cur_addr, z_strlen(trampolines_name) + 1,
                trampolines_name);
    cur_addr += z_strlen(trampolines_name) + 1;

    // step (9). store lookup table name
    const char *lookup_tabname = z_elf_get_lookup_tabname(b->elf);
    z_elf_write(b->elf, cur_addr, z_strlen(lookup_tabname) + 1, lookup_tabname);
    cur_addr += z_strlen(lookup_tabname) + 1;

    // step (10). store pipeline filename
    const char *pipe_filename = z_elf_get_pipe_filename(b->elf);
    z_elf_write(b->elf, cur_addr, z_strlen(pipe_filename) + 1, pipe_filename);
    cur_addr += z_strlen(pipe_filename) + 1;

    // step (11). store pipeline filename
    const char *shared_text_name = z_elf_get_shared_text_name(b->elf);
    z_elf_write(b->elf, cur_addr, z_strlen(shared_text_name) + 1,
                shared_text_name);
    cur_addr += z_strlen(shared_text_name) + 1;

    // step (12). store retaddr mapping filename
    const char *retaddr_mapping_name = z_elf_get_retaddr_mapping_name(b->elf);
    z_elf_write(b->elf, cur_addr, z_strlen(retaddr_mapping_name) + 1,
                retaddr_mapping_name);
    cur_addr += z_strlen(retaddr_mapping_name) + 1;

    // step (13). 16-byte alignment for fork server (avoid error in xmm)
    cur_addr = BITS_ALIGN_CELL(cur_addr, 4);

    // step (14). prepare the address of fork server
    b->fork_server_addr = cur_addr;
    z_info("fork server address: %#lx", b->fork_server_addr);
    if (b->prior_fork_server) {
        // over-write the loader_transfer_jmp_addr to the fork server
        KS_ASM_JMP(loader_transfer_jmp_addr, b->fork_server_addr);
        assert(ks_size == 5);
        z_elf_write(b->elf, loader_transfer_jmp_addr, ks_size, ks_encode);
    } else {
        // redirect __libc_start_main into fork server address
        addr_t load_main = z_elf_get_load_main(b->elf);
        if (z_elf_get_is_pie(b->elf)) {
            // size of "lea rdi, [rip + xxx]" is 7
            KS_ASM(load_main, "lea rdi, [rip %+ld];",
                   b->fork_server_addr - load_main - 7);
        } else {
            KS_ASM(load_main, "mov rdi, %#lx;", b->fork_server_addr);
        }
        assert(ks_size == 7);
        z_elf_write(b->elf, load_main, ks_size, ks_encode);
    }
}

Z_PRIVATE void __binary_setup_fork_server(Binary *b) {
    // step (0). create basic data structure
    addr_t cur_addr = b->fork_server_addr;

    // step (1). set down fork server
    uint8_t *fork_server_code = z_alloc(fork_server_bin_len, sizeof(uint8_t));
    memcpy(fork_server_code, fork_server_bin, fork_server_bin_len);

    if (z_elf_is_statically_linked(b->elf) && b->prior_fork_server) {
        // XXX: it is import to skip the TLS initialization for
        // statically-linked binaries when instrument_early option is on. Note
        // that if instrument_early is not on, we do not need to wipe off such
        // instructions because TLS will be initialized before main.
        // XXX: there is a bug for keystone to assemble such code, so we have to
        // encode it manually. See:
        // https://github.com/keystone-engine/keystone/issues/296

        /*
         * "mov DWORD PTR fs:0x2d0,eax;"
         * "mov DWORD PTR fs:0x2d4,eax;"
         */
        uint8_t tls_init_code[] = {0x64, 0x89, 0x04, 0x25, 0xd0, 0x02,
                                   0x00, 0x00, 0x64, 0x89, 0x04, 0x25,
                                   0xd4, 0x02, 0x00, 0x00};
        size_t tls_init_code_len = 16;

        // locate the code
        uint8_t *hole = memmem(fork_server_code, fork_server_bin_len,
                               tls_init_code, tls_init_code_len);
        if (!hole) {
            EXITME("TLS initialization code not found");
        }

        // wipe the code with nop
        memcpy(hole, z_x64_gen_nop(8), 8);
        memcpy(hole + 8, z_x64_gen_nop(8), 8);
    }

    z_elf_write(b->elf, cur_addr, fork_server_bin_len, fork_server_code);
    z_free(fork_server_code);
    cur_addr += fork_server_bin_len;

    // step (2). set jump gadget (default to original main/entrypoint)
    if (b->prior_fork_server) {
        addr_t entrypoint_addr = z_elf_get_ori_entry(b->elf);
        KS_ASM_JMP(cur_addr, entrypoint_addr);
        z_elf_write(b->elf, cur_addr, ks_size, ks_encode);
        cur_addr += 5;
    } else {
        addr_t main_addr = z_elf_get_main(b->elf);
        KS_ASM_JMP(cur_addr, main_addr);
        z_elf_write(b->elf, cur_addr, ks_size, ks_encode);
        cur_addr += 5;
    }

    // step (3). 8-byte alignment for following data
    cur_addr = BITS_ALIGN_CELL(cur_addr, 3);

    // step (4). write down whether -e option is enabled
    uint64_t ei_enabled = (uint64_t)b->prior_fork_server;
    z_elf_write(b->elf, cur_addr, sizeof(ei_enabled), &ei_enabled);
    cur_addr += sizeof(ei_enabled);

    // step (5). set random patch address
    // TODO: random patch is disable currently
    b->random_patch_addr = BITS_ALIGN_CELL(cur_addr, 3);
    b->random_patch_num = 0;
    z_info("random patch address: %#lx", b->random_patch_addr);
}

Z_PRIVATE void __binary_setup_lookup_table(Binary *b) {
    b->lookup_table_addr = z_elf_get_lookup_table_addr(b->elf);
}

Z_PRIVATE void __binary_setup_retaddr_mapping(Binary *b) {
    // XXX: the memory layout of retaddr mapping"
    //      0  - 7 : number of entities
    //      8  - 15: address of real_unw_step
    //      16 - ??: mapping entities
    b->retaddr_mapping_addr = z_elf_get_retaddr_mapping_addr(b->elf);
    b->retaddr_entity_addr = b->retaddr_mapping_addr + 0x10;
    b->retaddr_n = 0;

    // XXX: we first set the number of entities as -1 to indicate this space is
    // useless
    int64_t n = -1;
    z_elf_write(b->elf, b->retaddr_mapping_addr, sizeof(int64_t), &n);
}

Z_PRIVATE void __binary_setup_tp_zone(Binary *b) {
    b->trampolines_addr = z_elf_get_trampolines_addr(b->elf);
    b->last_tp_addr = b->trampolines_addr;

    // insert a NULL Trampoline to indicate terminal
    assert(sizeof(Trampoline) <= sizeof(null_buf));
    z_elf_write(b->elf, b->trampolines_addr, sizeof(Trampoline),
                (void *)null_buf);
    b->trampolines_addr += sizeof(Trampoline);
}

Z_API Binary *z_binary_open(const char *pathname, bool prior_fork_server) {
    // step (0). create a binary struct.
    Binary *b = STRUCT_ALLOC(Binary);
    b->original_filename = z_strdup(pathname);
    b->shadow_main = INVALID_ADDR;
    b->shadow_start = INVALID_ADDR;

    b->prior_fork_server = prior_fork_server;

    // step (1). setup elf
    b->elf = z_elf_open(b->original_filename, !prior_fork_server);

    // step (2). setup loader
    __binary_setup_loader(b);

    // step (3). setup lookup table
    __binary_setup_lookup_table(b);

    // step (4). setup fork server
    __binary_setup_fork_server(b);

    // step (5). setup trampoline zone
    __binary_setup_tp_zone(b);

    // step (6). setup retaddr mapping
    __binary_setup_retaddr_mapping(b);

    return b;
}

Z_API void z_binary_destroy(Binary *b) {
    z_elf_destroy(b->elf);

    z_free((char *)b->original_filename);

    g_hash_table_destroy(b->mmapped_pages);

    z_free(b);
}

Z_API void z_binary_fsync(Binary *b) {
    // sync ELF
    z_elf_fsync(b->elf);
}

Z_API void z_binary_save(Binary *b, const char *pathname) {
    // save ELF
    z_elf_save(b->elf, pathname);
}

Z_API void z_binary_create_snapshot(Binary *b, const char *pathname) {
    z_elf_create_snapshot(b->elf, pathname);
}

Z_API void z_binary_insert_utp(Binary *b, addr_t utp_addr, const uint8_t *utp,
                               const size_t utp_size) {
    assert(b != NULL);

    if (utp_size > PAGE_SIZE) {
        EXITME("utp size is too large [%#lx]", utp_size);
    }

    Snode *snode = z_snode_create(utp_addr, utp_size, NULL, NULL);
    addr_t mmap_addr = 0;
    size_t mmap_size = 0;
    if (!z_elf_insert_utp(b->elf, snode, &mmap_addr, &mmap_size)) {
        EXITME("Insert utp into an overlapped region: %#lx", utp_addr);
    }

    z_trace("mmap address (%#lx) and size (%#lx)", mmap_addr, mmap_size);

    // update last tp
    addr_t next_tp_offset = b->trampolines_addr - b->last_tp_addr;
    z_elf_write(b->elf, b->last_tp_addr + offsetof(Trampoline, next_tp_offset),
                sizeof(size_t), &next_tp_offset);
    b->last_tp_addr = b->trampolines_addr;

    // emit this utp
    z_elf_write(b->elf, b->trampolines_addr + offsetof(Trampoline, mmap_addr),
                sizeof(void *), &mmap_addr);
    z_elf_write(b->elf, b->trampolines_addr + offsetof(Trampoline, mmap_size),
                sizeof(size_t), &mmap_size);
    z_elf_write(b->elf, b->trampolines_addr + offsetof(Trampoline, tp_addr),
                sizeof(void *), &utp_addr);
    z_elf_write(b->elf, b->trampolines_addr + offsetof(Trampoline, tp_size),
                sizeof(size_t), &utp_size);
    z_elf_write(b->elf,
                b->trampolines_addr + offsetof(Trampoline, next_tp_offset),
                sizeof(size_t), (char *)null_buf);
    b->trampolines_addr += sizeof(Trampoline);
    z_elf_write(b->elf, b->trampolines_addr, utp_size, utp);
    b->trampolines_addr += utp_size;

    __binary_align_trampolines_addr(b);
}

Z_API addr_t z_binary_insert_shadow_code(Binary *b, const uint8_t *sc,
                                         const size_t sc_size) {
    addr_t cur_shadow_addr = b->trampolines_addr;

    z_elf_write(b->elf, b->trampolines_addr, sc_size, sc);
    b->trampolines_addr += sc_size;

    return cur_shadow_addr;
}

Z_API void z_binary_update_lookup_table(Binary *b, addr_t ori_addr,
                                        addr_t shadow_addr) {
    Elf64_Shdr *text = z_elf_get_shdr_text(b->elf);
    addr_t text_addr = text->sh_addr;

    if (ori_addr < text_addr)
        EXITME("too small address (%#lx) compared to .text (%#lx)", ori_addr,
               text_addr);

    size_t cell_num = ori_addr - text_addr;
    if (cell_num > LOOKUP_TABLE_CELL_NUM)
        EXITME("too big address (%#lx) compared to .text (%#lx)", ori_addr,
               text_addr);
    addr_t cell_addr = b->lookup_table_addr + cell_num * LOOKUP_TABLE_CELL_SIZE;

    if (shadow_addr > LOOKUP_TABLE_CELL_MASK)
        EXITME("too big shadow address (%#lx)", shadow_addr);

    z_elf_write(b->elf, cell_addr, LOOKUP_TABLE_CELL_SIZE,
                (uint8_t *)(&shadow_addr));
}

Z_API bool z_binary_check_state(Binary *b, ELFState state) {
    return z_elf_check_state(b->elf, state);
}

Z_API void z_binary_new_retaddr_entity(Binary *b, addr_t shadow_retaddr,
                                       addr_t ori_retaddr) {
    // update retaddr_n first
    b->retaddr_n += 1;
    z_elf_write(b->elf, b->retaddr_mapping_addr, sizeof(size_t),
                &(b->retaddr_n));

    uint32_t addr_buf;
    // insert shadow_retaddr
    addr_buf = (uint32_t)shadow_retaddr;
    assert((addr_t)addr_buf == shadow_retaddr);
    z_elf_write(b->elf, b->retaddr_entity_addr, sizeof(uint32_t), &addr_buf);
    b->retaddr_entity_addr += sizeof(uint32_t);

    // insert ori_retaddr
    addr_buf = (uint32_t)ori_retaddr;
    assert((addr_t)addr_buf == ori_retaddr);
    z_elf_write(b->elf, b->retaddr_entity_addr, sizeof(uint32_t), &addr_buf);
    b->retaddr_entity_addr += sizeof(uint32_t);
}


================================================
FILE: src/binary.h
================================================
/*
 * binary.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __BINARY_H
#define __BINARY_H

#include "buffer.h"
#include "config.h"
#include "elf_.h"
#include "interval_splay.h"

#include <gmodule.h>

typedef addr_t bb_t;

/*
 * Binary: used to story patch meta-information.
 *
 * ELF virtual memory layout can be found in elf_.h
 */
STRUCT(Binary, {
    const char *original_filename;  // Path of input file
    ELF *elf;                       // Basic ELF information
    addr_t shadow_main;             // Address of shadow main function
    addr_t shadow_start;            // Address of shadow _start function

    // Loader
    addr_t loader_addr;  // Address of loader

    // Loader info for uTP (TramPolines for ucall/ujmp)
    // XXX: the mmapped_pages seems useless currently (delete it maybe?)
    GHashTable *mmapped_pages;  // Hashset of mmapped pages

    // Fork server and random patcher
    addr_t fork_server_addr;   // Address of fork server
    addr_t random_patch_addr;  // Address of random patch table
    addr_t random_patch_num;   // Number of random patch table
    bool prior_fork_server;    // Whether we need to defer the fork server

    // Lookup table
    addr_t lookup_table_addr;  // Address of lookup table

    // Retaddr mapping
    size_t retaddr_n;             // Number of retaddr mapping entities
    addr_t retaddr_mapping_addr;  // Address of the retaddr mapping
    addr_t retaddr_entity_addr;   // Address of the next retaddr mapping entity

    // Shadow Code and Trampolines
    addr_t trampolines_addr;  // Next avaiable address of trampolines
    addr_t last_tp_addr;
});

DECLARE_GETTER(Binary, binary, ELF *, elf);
DECLARE_GETTER(Binary, binary, const char *, original_filename);
DECLARE_GETTER(Binary, binary, addr_t, trampolines_addr);
DECLARE_GETTER(Binary, binary, addr_t, shadow_main);
DECLARE_GETTER(Binary, binary, addr_t, shadow_code_addr);
DECLARE_SETTER(Binary, binary, addr_t, shadow_main);
DECLARE_SETTER(Binary, binary, addr_t, shadow_start);
DECLARE_SETTER(Binary, binary, ELFState, elf_state);

/*
 * Construct a binary for given file.
 */
Z_API Binary *z_binary_open(const char *in_filename, bool prior_fork_server);

/*
 * Destructor of Binary
 */
Z_API void z_binary_destroy(Binary *b);

/*
 * Save binary
 */
Z_API void z_binary_save(Binary *b, const char *pathname);

/*
 * Create a snapshot for current Binary.
 * Differnt from z_binary_save, this Binary's main body (except loookup tabel
 * and shadow) will remain unchanged even future patches are applied.
 */
Z_API void z_binary_create_snapshot(Binary *b, const char *pathname);

/*
 * Insert a new uTP
 */
// XXX: currently we do not use uTP in the actual rewriting, but it will be
// extremely useful when we start to handle overlapped jmp bridges.
Z_API void z_binary_insert_utp(Binary *b, addr_t utp_addr, const uint8_t *utp,
                               const size_t utp_size);

/*
 * Insert a new piece of shadow code, and return the address of the shadow code
 */
Z_API addr_t z_binary_insert_shadow_code(Binary *b, const uint8_t *sc,
                                         const size_t sc_size);

/*
 * Notify binary that all shadow code has been inserted
 */
Z_API void z_binary_shadow_code_notify(Binary *b, addr_t shadow_main);

/*
 * Add a look up cell
 */
Z_API void z_binary_update_lookup_table(Binary *b, addr_t ori_addr,
                                        addr_t shadow_addr);

/*
 * Sync binary with underlying files
 */
Z_API void z_binary_fsync(Binary *b);

/*
 * Wrapper for z_elf_check_state()
 */
Z_API bool z_binary_check_state(Binary *b, ELFState state);

/*
 * Add a new retaddr entity
 */
Z_API void z_binary_new_retaddr_entity(Binary *b, addr_t shadow_retaddr,
                                       addr_t ori_retaddr);
#endif


================================================
FILE: src/buffer.c
================================================
/*
 * buffer.c
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "buffer.h"
#include "utils.h"

/*
 * Extend buffer's chunk so that it can contain at lease new_chunk_size bytes
 */
Z_PRIVATE void __buffer_extend(Buffer *buf, size_t new_chunk_size);

/*
 * Create an empty buffer whose chunk can contain at lease size bytes
 */
Z_PRIVATE Buffer *__buffer_new(size_t size);

Z_PRIVATE Buffer *__buffer_new(size_t size) {
    // Get chunk_size
    size_t chunk_size = 8;
    if (size >= 1) {
        chunk_size = size;
        chunk_size |= (chunk_size >> 1);
        chunk_size |= (chunk_size >> 2);
        chunk_size |= (chunk_size >> 4);
        chunk_size |= (chunk_size >> 8);
        chunk_size |= (chunk_size >> 16);
        chunk_size |= (chunk_size >> 32);
        chunk_size += 1;
    }
    assert(chunk_size > size);

    z_trace("get chunk_size (%#lx) for requested size (%#lx)", chunk_size,
            size);

    // Create a buffer
    Buffer *buf = STRUCT_ALLOC(Buffer);
    buf->raw_buf = (uint8_t *)z_alloc(chunk_size, sizeof(uint8_t));
    buf->size = 0;
    buf->chunk_size = chunk_size;

    return buf;
}

Z_PRIVATE void __buffer_extend(Buffer *buf, size_t new_chunk_size) {
    assert(buf != NULL);
    z_trace("extend to %#lx bytes, original one is %#lx bytes", new_chunk_size,
            buf->chunk_size);
    while (new_chunk_size >= buf->chunk_size) {
        if (buf->chunk_size * 2 <= buf->chunk_size) {
            EXITME("too big chunk size (%#lx)", buf->chunk_size);
        }
        buf->raw_buf = z_realloc(buf->raw_buf, buf->chunk_size * 2);
        buf->chunk_size *= 2;
    }
}

/*
 * Setter and Getter
 */
DEFINE_GETTER(Buffer, buffer, size_t, size);
DEFINE_GETTER(Buffer, buffer, uint8_t *, raw_buf);

Z_API Buffer *z_buffer_create(const uint8_t *ptr, size_t size) {
    Buffer *buf = __buffer_new(size);
    if (ptr != NULL) {
        memcpy(buf->raw_buf, ptr, size);
    } else {
        if (size) {
            EXITME("try to create a buffer with NULL ptr and positive size");
        }
    }
    buf->size = size;
    return buf;
}

Z_API void z_buffer_push(Buffer *buf, uint8_t ch) {
    assert(buf != NULL);
    __buffer_extend(buf, buf->size + 1);
    buf->raw_buf[buf->size] = ch;
    buf->size += 1;
}

Z_API void z_buffer_append(Buffer *dst, Buffer *src) {
    assert(dst != NULL && src != NULL);
    __buffer_extend(dst, dst->size + src->size);
    memcpy(dst->raw_buf + dst->size, src->raw_buf, src->size);
    dst->size += src->size;
}

Z_API void z_buffer_append_raw(Buffer *buf, const uint8_t *ptr, size_t size) {
    assert(buf != NULL);
    if (ptr != NULL) {
        __buffer_extend(buf, buf->size + size);
        memcpy(buf->raw_buf + buf->size, ptr, size);
        buf->size += size;
    }
}

Z_API Buffer *z_buffer_read_file(const char *pathname) {
    FILE *f = z_fopen(pathname, "rb");

    // Get file size
    z_fseek(f, 0L, SEEK_END);
    size_t f_size = (size_t)z_ftell(f);

    // Create a buffer
    Buffer *buf = (Buffer *)__buffer_new(f_size);

    // Read file
    z_fseek(f, 0L, SEEK_SET);
    size_t r_size = z_fread(buf->raw_buf, sizeof(uint8_t), f_size, f);
    if (r_size < f_size) {
        EXITME("read %lu bytes from \"%s\", but %lu bytes expected", r_size,
               pathname, f_size);
    }
    buf->size = r_size;

    z_fclose(f);

    z_trace("successfully read %lu bytes from \"%s\"", f_size, pathname);
    return buf;
}

Z_API void z_buffer_write_file(Buffer *buf, const char *pathname) {
    assert(buf != NULL);
    FILE *f = z_fopen(pathname, "wb");

    size_t size = z_fwrite(buf->raw_buf, sizeof(uint8_t), buf->size, f);
    if (size != buf->size) {
        EXITME(
            "fail when writing content to \"%s\", expect %ld bytes, but only "
            "%ld bytes",
            pathname, buf->size, size);
    }

    z_fclose(f);
}

Z_API Buffer *z_buffer_dup(Buffer *src) {
    assert(src != NULL);
    Buffer *dst = STRUCT_ALLOC(Buffer);
    dst->size = src->size;
    dst->chunk_size = src->chunk_size;
    dst->raw_buf = z_alloc(dst->chunk_size, sizeof(uint8_t));
    memcpy(dst->raw_buf, src->raw_buf, dst->size);
    return dst;
}

Z_API void z_buffer_destroy(Buffer *buf) {
    assert(buf != NULL);
    // Free Buffer.buf
    memset(buf->raw_buf, 0, buf->size);
    z_free((void *)buf->raw_buf);

    // Free Buffer itself
    memset(buf, 0, sizeof(Buffer));
    z_free((void *)buf);
}

Z_API uint8_t *z_buffer_seek(Buffer *buf, size_t offset, int whence) {
    assert(buf != NULL);
    if (offset >= buf->size) {
        z_warn("offset (%lu) is bigger than buffer size (%lu)", offset,
               buf->size);
        return NULL;
    }

    size_t st_offset;
    if (whence == SEEK_END) {
        // The last byte should be 0 from SEEK_END
        st_offset = buf->size - offset - 1;
    } else if (whence == SEEK_SET) {
        st_offset = offset;
    } else {
        z_warn("invalid whence (%d)", whence);
        return NULL;
    }

    return (buf->raw_buf + st_offset);
}

Z_API size_t z_buffer_tell(Buffer *buf, const uint8_t *ptr, int whence) {
    assert(buf != NULL);
    if (ptr < buf->raw_buf) {
        z_warn("ptr is smaller than buf->raw_buf");
        return SIZE_MAX;
    }

    if (ptr - buf->raw_buf >= buf->size) {
        z_warn("ptr is bigger than buf->raw_buf + buf->size");
        return SIZE_MAX;
    }

    if (whence == SEEK_END) {
        return (buf->size - (ptr - buf->raw_buf) - 1);
    } else if (whence == SEEK_SET) {
        return (ptr - buf->raw_buf);
    } else {
        z_warn("invalid whence (%d)", whence);
        return SIZE_MAX;
    }
}

Z_API void z_buffer_truncate(Buffer *buf, size_t index) {
    assert(buf != NULL);
    if (index >= buf->size) {
        z_trace("index is out of buffer (%lu >= %lu)", index, buf->size);
        return;
    }

    buf->size = index;
}

Z_API void z_buffer_fill(Buffer *buf, uint8_t ch, size_t size) {
    assert(buf != NULL);
    if (size < buf->size) {
        z_warn(
            "buffer's original size (%lu) is bigger than requested size (%lu)",
            buf->size, size);
        return;
    }
    __buffer_extend(buf, size);
    if (ch != 0) {
        // Little optimization
        memset(buf->raw_buf + buf->size, ch, size - buf->size);
    }
    buf->size = size;
}


================================================
FILE: src/buffer.h
================================================
/*
 * buffer.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __BUFFER_H
#define __BUFFER_H

#include "config.h"

/*
 * Buffer structure for all heap-allocated data
 */
STRUCT(Buffer, {
    uint8_t *raw_buf;
    size_t size;
    size_t chunk_size;
});

/*
 * Setter and Getter
 */
DECLARE_GETTER(Buffer, buffer, size_t, size);
DECLARE_GETTER(Buffer, buffer, uint8_t *, raw_buf);

/*
 * Create a buffer from a raw pointer.
 * If ptr == NULL and size == 0, return an empty buffer
 */
Z_API Buffer *z_buffer_create(const uint8_t *ptr, size_t size);

/*
 * Push a ch into buffer
 */
Z_API void z_buffer_push(Buffer *buf, uint8_t ch);

/*
 * Append src buffer into the end of buffer dst
 */
Z_API void z_buffer_append(Buffer *dst, Buffer *src);

/*
 * Append raw pointer into the end of buffer
 */
Z_API void z_buffer_append_raw(Buffer *buf, const uint8_t *ptr, size_t size);

/*
 * Fill buffer with ch to size bytes
 */
Z_API void z_buffer_fill(Buffer *buf, uint8_t ch, size_t size);

/*
 * Create a buffer and read content from pathname
 */
Z_API Buffer *z_buffer_read_file(const char *pathname);

/*
 * Create a file and write content to pathname
 */
Z_API void z_buffer_write_file(Buffer *buf, const char *pathname);

/*
 * Duplicate a buffer
 */
Z_API Buffer *z_buffer_dup(Buffer *src);

/*
 * Destructor of Buffer
 */
Z_API void z_buffer_destroy(Buffer *buf);

/*
 * Seek an offset, return a pointer to that offset.
 * Return NULL if the offset is invalid.
 */
Z_API uint8_t *z_buffer_seek(Buffer *buf, size_t offset, int whence);

/*
 * Tell an pointer, return the pointer's offset on the buffer.
 * Return MAX of size_t if the pointer is not on the buffer.
 */
Z_API size_t z_buffer_tell(Buffer *buf, const uint8_t *ptr, int whence);

/*
 * Truncate all content after index (included).
 */
Z_API void z_buffer_truncate(Buffer *buf, size_t index);

#endif


================================================
FILE: src/capstone_.c
================================================
/*
 * capstone_.c
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "capstone_.h"
#include "utils.h"

#define __FLG_READ(F) static uint64_t __FLG_READ_##F = X86_EFLAGS_TEST_##F
__FLG_READ(OF);
__FLG_READ(SF);
__FLG_READ(ZF);
__FLG_READ(AF);
__FLG_READ(CF);
__FLG_READ(PF);
#undef __FLG_READ

#define __FLG_WRITE(F)                                                      \
    static uint64_t __FLG_WRITE_##F =                                       \
        X86_EFLAGS_MODIFY_##F | X86_EFLAGS_RESET_##F | X86_EFLAGS_SET_##F | \
        X86_EFLAGS_UNDEFINED_##F
__FLG_WRITE(OF);
__FLG_WRITE(SF);
__FLG_WRITE(ZF);
__FLG_WRITE(AF);
__FLG_WRITE(CF);
__FLG_WRITE(PF);
#undef __FLA_WRITE

/*
 * Mapping a eflag action into individual flag's read state
 */
Z_PRIVATE FLGState __capstone_mapping_flg_read(uint64_t flg_state);

/*
 * Mapping a eflag action into individual flag's write state
 */
Z_PRIVATE FLGState __capstone_mapping_flg_write(uint64_t flg_state);

/*
 * Mapping CAPSTONE general purpose register info into GPRState. Here we mapping
 * a sub-register into its complete form.
 *
 * More information please refer to
 *   https://www.tortall.net/projects/yasm/manual/html/arch-x86-registers.html.
 */
Z_PRIVATE GPRState __capstone_mapping_pgr(x86_reg reg_id);

/*
 * Filter CAPSTONE general purpose register, we only need 32-bit and 64-bit GPR
 * here
 */
Z_PRIVATE GPRState __capstone_filter_pgr(x86_reg reg_id);

Z_PRIVATE FLGState __capstone_mapping_flg_write(uint64_t flg_state) {
#define __FLG_MAPPING_WRITE(fs, F)         \
    do {                                   \
        if (flg_state & __FLG_WRITE_##F) { \
            (fs) |= FLGSTATE_##F;          \
        }                                  \
    } while (0)

    FLGState fs = 0;
    __FLG_MAPPING_WRITE(fs, OF);
    __FLG_MAPPING_WRITE(fs, SF);
    __FLG_MAPPING_WRITE(fs, ZF);
    __FLG_MAPPING_WRITE(fs, AF);
    __FLG_MAPPING_WRITE(fs, CF);
    __FLG_MAPPING_WRITE(fs, PF);
    return fs;

#undef __FLG_MAPPING_WRITE
}

Z_PRIVATE FLGState __capstone_mapping_flg_read(uint64_t flg_state) {
#define __FLG_MAPPING_READ(fs, F)         \
    do {                                  \
        if (flg_state & __FLG_READ_##F) { \
            (fs) |= FLGSTATE_##F;         \
        }                                 \
    } while (0)

    FLGState fs = 0;
    __FLG_MAPPING_READ(fs, OF);
    __FLG_MAPPING_READ(fs, SF);
    __FLG_MAPPING_READ(fs, ZF);
    __FLG_MAPPING_READ(fs, AF);
    __FLG_MAPPING_READ(fs, CF);
    __FLG_MAPPING_READ(fs, PF);
    return fs;

#undef __FLG_MAPPING_READ
}

Z_PRIVATE GPRState __capstone_mapping_pgr(x86_reg reg_id) {
#define __GPR_MAPPING_1(T) \
    case X86_REG_##T##H:   \
    case X86_REG_##T##L:   \
    case X86_REG_##T##X:   \
    case X86_REG_E##T##X:  \
    case X86_REG_R##T##X:  \
        return GPRSTATE_R##T##X

#define __GPR_MAPPING_2(T) \
    case X86_REG_##T:      \
    case X86_REG_##T##L:   \
    case X86_REG_E##T:     \
    case X86_REG_R##T:     \
        return GPRSTATE_R##T

#define __GPR_MAPPING_3(T) \
    case X86_REG_##T##B:   \
    case X86_REG_##T##W:   \
    case X86_REG_##T##D:   \
    case X86_REG_##T:      \
        return GPRSTATE_##T

    switch (reg_id) {
        __GPR_MAPPING_1(A);
        __GPR_MAPPING_1(B);
        __GPR_MAPPING_1(C);
        __GPR_MAPPING_1(D);

        __GPR_MAPPING_2(DI);
        __GPR_MAPPING_2(SI);
        __GPR_MAPPING_2(BP);

        __GPR_MAPPING_3(R8);
        __GPR_MAPPING_3(R9);
        __GPR_MAPPING_3(R10);
        __GPR_MAPPING_3(R11);
        __GPR_MAPPING_3(R12);
        __GPR_MAPPING_3(R13);
        __GPR_MAPPING_3(R14);
        __GPR_MAPPING_3(R15);

        default:
            return 0;
    }

#undef __GPR_MAPPING_1
#undef __GPR_MAPPING_2
#undef __GPR_MAPPING_3
}

Z_PRIVATE GPRState __capstone_filter_pgr(x86_reg reg_id) {
#define __GPR_FILTER_1(T) \
    case X86_REG_E##T##X: \
    case X86_REG_R##T##X: \
        return GPRSTATE_R##T##X

#define __GPR_FILTER_2(T) \
    case X86_REG_E##T:    \
    case X86_REG_R##T:    \
        return GPRSTATE_R##T

#define __GPR_FILTER_3(T) \
    case X86_REG_##T##D:  \
    case X86_REG_##T:     \
        return GPRSTATE_##T

    switch (reg_id) {
        __GPR_FILTER_1(A);
        __GPR_FILTER_1(B);
        __GPR_FILTER_1(C);
        __GPR_FILTER_1(D);

        __GPR_FILTER_2(DI);
        __GPR_FILTER_2(SI);
        __GPR_FILTER_2(BP);

        __GPR_FILTER_3(R8);
        __GPR_FILTER_3(R9);
        __GPR_FILTER_3(R10);
        __GPR_FILTER_3(R11);
        __GPR_FILTER_3(R12);
        __GPR_FILTER_3(R13);
        __GPR_FILTER_3(R14);
        __GPR_FILTER_3(R15);

        default:
            return 0;
    }

#undef __GPR_FILTER_1
#undef __GPR_FILTER_2
#undef __GPR_FILTER_3
}

Z_API bool z_capstone_is_call(const cs_insn *inst) {
    return (inst->id == X86_INS_CALL) || (inst->id == X86_INS_LCALL);
}

Z_API bool z_capstone_is_jmp(const cs_insn *inst) {
    return (inst->id == X86_INS_JMP) || (inst->id == X86_INS_LJMP);
}

Z_API bool z_capstone_is_xbegin(const cs_insn *inst) {
    return inst->id == X86_INS_XBEGIN;
}

Z_API bool z_capstone_is_ret(const cs_insn *inst) {
    return inst->id == X86_INS_RET;
}

Z_API bool z_capstone_is_loop(const cs_insn *inst) {
    switch (inst->id) {
        case X86_INS_LOOP:
        case X86_INS_LOOPE:
        case X86_INS_LOOPNE:
            return true;
        default:
            return false;
    }
}
Z_API bool z_capstone_is_cjmp(const cs_insn *inst) {
    switch (inst->id) {
        case X86_INS_JAE:
        case X86_INS_JA:
        case X86_INS_JBE:
        case X86_INS_JB:
        case X86_INS_JCXZ:
        case X86_INS_JECXZ:
        case X86_INS_JE:
        case X86_INS_JGE:
        case X86_INS_JG:
        case X86_INS_JLE:
        case X86_INS_JL:
        case X86_INS_JNE:
        case X86_INS_JNO:
        case X86_INS_JNP:
        case X86_INS_JNS:
        case X86_INS_JO:
        case X86_INS_JP:
        case X86_INS_JRCXZ:
        case X86_INS_JS:
            return true;
        default:
            return false;
    }
}

Z_API bool z_capstone_is_terminator(const cs_insn *inst) {
    // TODO: better non-return analysis? (light-weight approach)
    if (z_capstone_is_jmp(inst))
        return true;
    if (z_capstone_is_cjmp(inst))
        return false;
    if (z_capstone_is_call(inst))
        return false;
    if (z_capstone_is_loop(inst))
        return false;
    if (z_capstone_is_xbegin(inst))
        return false;

    // check HLT first
    if (inst->id == X86_INS_HLT) {
        return true;
    }

    cs_detail *detail = inst->detail;
    for (int32_t i = 0; i < detail->groups_count; i++) {
        switch (detail->groups[i]) {
            case X86_GRP_JUMP:
            case X86_GRP_CALL:
            case X86_GRP_BRANCH_RELATIVE:
                EXITME(
                    "branch-relative instruction should be catched before "
                    "[%#lx:\t%s %s]",
                    inst->address, inst->mnemonic, inst->op_str);
            /*
             * instructions in RET and IRET group will change the control flow,
             * but most instructions (except HLT) in INT and PRIVILEGE groups
             * seem not. Please refer to
             * https://github.com/aquynh/capstone/blob/master/arch/X86/X86MappingInsn_reduce.inc
             * for more information
             */
            case X86_GRP_RET:
            case X86_GRP_IRET:
                return true;
            case X86_GRP_INT:
            case X86_GRP_PRIVILEGE:
            default:
                continue;
        }
    }

    return false;
}

Z_API bool z_capstone_is_rare(const cs_insn *inst) {
    // we maintain a rare instruction list to benifit hint collection
    switch (inst->id) {
        case X86_INS_OUT:
        case X86_INS_OUTSB:
        case X86_INS_OUTSD:
        case X86_INS_OUTSW:
        case X86_INS_IN:
        case X86_INS_IRETD:
        case X86_INS_FLD:
        case X86_INS_ENTER:
        case X86_INS_XCHG:
            return true;
        default:
            return false;
    }
}

Z_API RegState *z_capstone_get_register_state(const cs_insn *inst) {
    RegState *rs = STRUCT_ALLOC(RegState);

    // step (1). get grp
    cs_regs regs_read, regs_write;
    uint8_t regs_read_count, regs_write_count;
    if (cs_regs_access(cs, inst, regs_read, &regs_read_count, regs_write,
                       &regs_write_count)) {
        EXITME("fail on cs_regs_access");
    }
    rs->gpr_read = rs->gpr_write = 0;
    rs->gpr_read_32_64 = rs->gpr_write_32_64 = 0;
    // step (1.1). read
    for (int i = 0; i < regs_read_count; i++) {
        rs->gpr_read |= __capstone_mapping_pgr(regs_read[i]);
        rs->gpr_read_32_64 |= __capstone_filter_pgr(regs_read[i]);
    }
    // step (1.2). write
    for (int i = 0; i < regs_write_count; i++) {
        rs->gpr_write |= __capstone_mapping_pgr(regs_write[i]);
        rs->gpr_write_32_64 |= __capstone_filter_pgr(regs_write[i]);
    }

    // step (2). get sse
#define __SSE_MAPPING(T, N, reg, states) \
    do {                                 \
        if ((reg) == X86_REG_##T##N) {   \
            (states) |= T##STATE_##T##N; \
        }                                \
    } while (0)

#define __SSE_MAPPING_FOR_ALL(T, reg, states) \
    do {                                      \
        __SSE_MAPPING(T, 0, reg, states);     \
        __SSE_MAPPING(T, 1, reg, states);     \
        __SSE_MAPPING(T, 2, reg, states);     \
        __SSE_MAPPING(T, 3, reg, states);     \
        __SSE_MAPPING(T, 4, reg, states);     \
        __SSE_MAPPING(T, 5, reg, states);     \
        __SSE_MAPPING(T, 6, reg, states);     \
        __SSE_MAPPING(T, 7, reg, states);     \
        __SSE_MAPPING(T, 8, reg, states);     \
        __SSE_MAPPING(T, 9, reg, states);     \
        __SSE_MAPPING(T, 10, reg, states);    \
        __SSE_MAPPING(T, 11, reg, states);    \
        __SSE_MAPPING(T, 12, reg, states);    \
        __SSE_MAPPING(T, 13, reg, states);    \
        __SSE_MAPPING(T, 14, reg, states);    \
        __SSE_MAPPING(T, 15, reg, states);    \
    } while (0)

    for (int i = 0; i < regs_read_count; i++) {
        __SSE_MAPPING_FOR_ALL(XMM, regs_read[i], rs->xmm_read);
        __SSE_MAPPING_FOR_ALL(YMM, regs_read[i], rs->ymm_read);
        __SSE_MAPPING_FOR_ALL(ZMM, regs_read[i], rs->zmm_read);
    }
    for (int i = 0; i < regs_write_count; i++) {
        __SSE_MAPPING_FOR_ALL(XMM, regs_write[i], rs->xmm_write);
        __SSE_MAPPING_FOR_ALL(YMM, regs_write[i], rs->ymm_write);
        __SSE_MAPPING_FOR_ALL(ZMM, regs_write[i], rs->zmm_write);
    }

#undef __SSE_MAPPING
#undef __SSE_MAPPING_FOR_ALL

    // step (3). get flg
    rs->flg_read = rs->flg_write = 0;
    // step (3.0). check FPU first
    for (int i = 0; i < inst->detail->groups_count; i++) {
        if (inst->detail->groups[i] == X86_GRP_FPU) {
            goto DONE;
        }
    }
    // step (3.1). get flg state
    rs->flg_read = __capstone_mapping_flg_read(inst->detail->x86.eflags);
    rs->flg_write = __capstone_mapping_flg_write(inst->detail->x86.eflags);

    /*
     * XXX: capstone: *sbb* and *adc* instructions do not have any TEST_CF bit.
     * Hence, we use a very conservative approach to get rs->flg_read. Please
     * refer to https://github.com/aquynh/capstone/issues/1696 for more
     * information.
     *
     * However, we do not remove previous rs->flg_read code. Maybe one day we
     * can patch capstone to enable a more powerful optimization.
     */
    // TODO: prepare our own patch for capstone and keystone.
    for (int i = 0; i < regs_read_count; i++) {
        if (regs_read[i] == X86_REG_EFLAGS) {
            rs->flg_read = FLGSTATE_ALL;
            break;
        }
    }

DONE:
    return rs;
}

// XXX: call qword byte [xxx]
Z_API bool z_capstone_is_const_mem_ucall(const cs_insn *inst,
                                         addr_t *addr_ptr) {
    // first check that it is a jump instruction
    if (inst->id != X86_INS_CALL) {
        return false;
    }

    // then check that it only has one operand
    cs_detail *detail = inst->detail;
    if (detail->x86.op_count != 1) {
        return false;
    }

    // then check the operand is a qword memory
    cs_x86_op *op = &(detail->x86.operands[0]);
    if (op->type != X86_OP_MEM || op->mem.base != X86_REG_INVALID ||
        op->mem.index != X86_REG_INVALID || op->size != 8) {
        return false;
    }

    // update addr_ptr
    if (addr_ptr) {
        *addr_ptr = op->mem.disp;
    }
    return true;
}

// XXX: call qword byte [rip+xxx]
Z_API bool z_capstone_is_pc_related_ucall(const cs_insn *inst,
                                          addr_t *addr_ptr) {
    // first check that it is a jump instruction
    if (inst->id != X86_INS_CALL) {
        return false;
    }

    // then check that it only has one operand
    cs_detail *detail = inst->detail;
    if (detail->x86.op_count != 1) {
        return false;
    }

    // then check the operand is a qword memory
    cs_x86_op *op = &(detail->x86.operands[0]);
    if (op->type != X86_OP_MEM || op->mem.base != X86_REG_RIP ||
        op->mem.index != X86_REG_INVALID || op->size != 8) {
        return false;
    }

    // update addr_ptr
    if (addr_ptr) {
        *addr_ptr = inst->address + inst->size + op->mem.disp;
    }
    return true;
}

// XXX: jmp qword byte [xxx]
Z_API bool z_capstone_is_const_mem_ujmp(const cs_insn *inst, addr_t *addr_ptr) {
    // first check that it is a jump instruction
    if (inst->id != X86_INS_JMP) {
        return false;
    }

    // then check that it only has one operand
    cs_detail *detail = inst->detail;
    if (detail->x86.op_count != 1) {
        return false;
    }

    // then check the operand is a qword memory
    cs_x86_op *op = &(detail->x86.operands[0]);
    if (op->type != X86_OP_MEM || op->mem.base != X86_REG_INVALID ||
        op->mem.index != X86_REG_INVALID || op->size != 8) {
        return false;
    }

    // update addr_ptr
    if (addr_ptr) {
        *addr_ptr = op->mem.disp;
    }
    return true;
}

// XXX: jmp qword byte [rip+xxx]
Z_API bool z_capstone_is_pc_related_ujmp(const cs_insn *inst,
                                         addr_t *addr_ptr) {
    // first check that it is a jump instruction
    if (inst->id != X86_INS_JMP) {
        return false;
    }

    // then check that it only has one operand
    cs_detail *detail = inst->detail;
    if (detail->x86.op_count != 1) {
        return false;
    }

    // then check the operand is a qword memory
    cs_x86_op *op = &(detail->x86.operands[0]);
    if (op->type != X86_OP_MEM || op->mem.base != X86_REG_RIP ||
        op->mem.index != X86_REG_INVALID || op->size != 8) {
        return false;
    }

    // update addr_ptr
    if (addr_ptr) {
        *addr_ptr = inst->address + inst->size + op->mem.disp;
    }
    return true;
}

Z_API void z_capstone_show_gpr_state(GPRState gpr_state) {
    z_info(
        "rax %d | rbx %d | rcx %d | rdx %d | rdi %d | rsi %d | rbp %d | r8 %d "
        "| r9 %d | r10 %d | r11 %d | r12 %d | r13 %d | r14 %d | r15 %d",
        (gpr_state >> 0) & 1UL, (gpr_state >> 1) & 1UL, (gpr_state >> 2) & 1UL,
        (gpr_state >> 3) & 1UL, (gpr_state >> 4) & 1UL, (gpr_state >> 5) & 1UL,
        (gpr_state >> 6) & 1UL, (gpr_state >> 7) & 1UL, (gpr_state >> 8) & 1UL,
        (gpr_state >> 9) & 1UL, (gpr_state >> 10) & 1UL,
        (gpr_state >> 11) & 1UL, (gpr_state >> 12) & 1UL,
        (gpr_state >> 13) & 1UL, (gpr_state >> 14) & 1UL);
}

Z_API void z_capstone_show_flg_state(FLGState flg_state) {
    z_info("OF %d | SF %d | ZF %d | AF %d | CF %d | PF %d",
           (flg_state >> 0) & 1UL, (flg_state >> 1) & 1UL,
           (flg_state >> 2) & 1UL, (flg_state >> 3) & 1UL,
           (flg_state >> 4) & 1UL, (flg_state >> 5) & 1UL);
}


================================================
FILE: src/capstone_.h
================================================
/*
 * capstone_.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __CAPSTONE__H
#define __CAPSTONE__H

/*
 * My own wrapper for capstone, which aims at extracting information from known
 * cs_insn structures. CS_DISASM is not included in this file because it is used
 * for disassembly instead of check cs_insn's features.
 */

#include "config.h"

#include <capstone/capstone.h>

/*
 * General Purposed Register
 */
#define CAPSTONE_FORALL_GPR(STATEMENT) \
    do {                               \
        STATEMENT(RAX);                \
        STATEMENT(RBX);                \
        STATEMENT(RCX);                \
        STATEMENT(RDX);                \
        STATEMENT(RBP);                \
        STATEMENT(RDI);                \
        STATEMENT(RSI);                \
        STATEMENT(R8);                 \
        STATEMENT(R9);                 \
        STATEMENT(R10);                \
        STATEMENT(R11);                \
        STATEMENT(R12);                \
        STATEMENT(R13);                \
        STATEMENT(R14);                \
        STATEMENT(R15);                \
    } while (0)

typedef enum gpr_state_t {
    GPRSTATE_RAX = (1UL << 0),
    GPRSTATE_RBX = (1UL << 1),
    GPRSTATE_RCX = (1UL << 2),
    GPRSTATE_RDX = (1UL << 3),
    GPRSTATE_RDI = (1UL << 4),
    GPRSTATE_RSI = (1UL << 5),
    GPRSTATE_RBP = (1UL << 6),  // <-- NO RSP HERE
    GPRSTATE_R8 = (1UL << 7),
    GPRSTATE_R9 = (1UL << 8),
    GPRSTATE_R10 = (1UL << 9),
    GPRSTATE_R11 = (1UL << 10),
    GPRSTATE_R12 = (1UL << 11),
    GPRSTATE_R13 = (1UL << 12),
    GPRSTATE_R14 = (1UL << 13),
    GPRSTATE_R15 = (1UL << 14),

    GPRSTATE_ALL = ((1UL << 15) - 1),
} GPRState;

/*
 * EFLAGS Register
 */
#define CAPSTONE_FORALL_FLG(STATEMENT) \
    do {                               \
        STATEMENT(OF);                 \
        STATEMENT(SF);                 \
        STATEMENT(ZF);                 \
        STATEMENT(AF);                 \
        STATEMENT(CF);                 \
        STATEMENT(PF);                 \
    } while (0)

typedef enum flg_state_t {
    FLGSTATE_OF = (1UL << 0),
    FLGSTATE_SF = (1UL << 1),
    FLGSTATE_ZF = (1UL << 2),
    FLGSTATE_AF = (1UL << 3),
    FLGSTATE_CF = (1UL << 4),
    FLGSTATE_PF = (1UL << 5),

    FLGSTATE_ALL = ((1UL << 6) - 1),
} FLGState;

/*
 * SSE Register
 */
#define CAPSTONE_FORALL_SSE(T, STATEMENT) \
    do {                                  \
        STATEMENT(T, 0);                  \
        STATEMENT(T, 1);                  \
        STATEMENT(T, 2);                  \
        STATEMENT(T, 3);                  \
        STATEMENT(T, 4);                  \
        STATEMENT(T, 5);                  \
        STATEMENT(T, 6);                  \
        STATEMENT(T, 7);                  \
        STATEMENT(T, 8);                  \
        STATEMENT(T, 9);                  \
        STATEMENT(T, 10);                 \
        STATEMENT(T, 11);                 \
        STATEMENT(T, 12);                 \
        STATEMENT(T, 13);                 \
        STATEMENT(T, 14);                 \
        STATEMENT(T, 15);                 \
    } while (0)

#define __SSE_DEFINE(T, N) T##STATE_##T##N = (1UL << N)
#define __SSE_DEFINE_ALL(enum_name, T) \
    typedef enum enum_name {           \
        __SSE_DEFINE(T, 0),            \
        __SSE_DEFINE(T, 1),            \
        __SSE_DEFINE(T, 2),            \
        __SSE_DEFINE(T, 3),            \
        __SSE_DEFINE(T, 4),            \
        __SSE_DEFINE(T, 5),            \
        __SSE_DEFINE(T, 6),            \
        __SSE_DEFINE(T, 7),            \
        __SSE_DEFINE(T, 8),            \
        __SSE_DEFINE(T, 9),            \
        __SSE_DEFINE(T, 10),           \
        __SSE_DEFINE(T, 11),           \
        __SSE_DEFINE(T, 12),           \
        __SSE_DEFINE(T, 13),           \
        __SSE_DEFINE(T, 14),           \
        __SSE_DEFINE(T, 15),           \
                                       \
        T##STATE_ALL = ~(0UL),         \
    } T##State;

__SSE_DEFINE_ALL(xmm_state_t, XMM);
__SSE_DEFINE_ALL(ymm_state_t, YMM);
__SSE_DEFINE_ALL(zmm_state_t, ZMM);

#undef __SSE_DEFINE_ALL
#undef __SSE_DEFINE

STRUCT(RegState, {
    GPRState gpr_read;
    GPRState gpr_read_32_64;
    GPRState gpr_write;
    GPRState gpr_write_32_64;
    FLGState flg_read;
    FLGState flg_write;
    XMMState xmm_read;
    XMMState xmm_write;
    YMMState ymm_read;
    YMMState ymm_write;
    ZMMState zmm_read;
    ZMMState zmm_write;
});

Z_API bool z_capstone_is_call(const cs_insn *inst);

Z_API bool z_capstone_is_jmp(const cs_insn *inst);

Z_API bool z_capstone_is_cjmp(const cs_insn *inst);

Z_API bool z_capstone_is_loop(const cs_insn *inst);

Z_API bool z_capstone_is_xbegin(const cs_insn *inst);

Z_API bool z_capstone_is_ret(const cs_insn *inst);

Z_API bool z_capstone_is_terminator(const cs_insn *inst);

Z_API bool z_capstone_is_rare(const cs_insn *inst);

Z_API bool z_capstone_is_pc_related_ujmp(const cs_insn *inst, addr_t *addr_ptr);

Z_API bool z_capstone_is_const_mem_ujmp(const cs_insn *inst, addr_t *addr_ptr);

Z_API bool z_capstone_is_pc_related_ucall(const cs_insn *inst,
                                          addr_t *addr_ptr);

Z_API bool z_capstone_is_const_mem_ucall(const cs_insn *inst, addr_t *addr_ptr);

Z_API RegState *z_capstone_get_register_state(const cs_insn *inst);

Z_API void z_capstone_show_gpr_state(GPRState gpr_state);

Z_API void z_capstone_show_flg_state(FLGState flg_state);

#endif


================================================
FILE: src/config.h
================================================
/*
 * config.h
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __CONFIG_H
#define __CONFIG_H

/*
 * Include basic headers
 */
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>

/*
 * Tool name and version
 */
#define OURTOOL "stoch-fuzz"
#define VERSION "1.1.0"

/*
 * Magic string to indicate the file is patched
 */
#define MAGIC_STRING "2015.05.02 Shanghai Snow"
#define MAGIC_NUMBER 0x527569787565

/*
 * Genral macro and types
 */
#define STRING(x) STRING_2(x)
#define STRING_2(x) #x

// error code for EXITME
#define MY_ERR_CODE 233

#define Z_API __attribute__((visibility("hidden")))
#define Z_PRIVATE __attribute__((visibility("hidden"))) static inline
#define Z_PUBLIC __attribute__((visibility("default")))
#define Z_RESERVED __attribute__((unused))

#define PAGE_SIZE_POW2 PAGE_SHIFT

#define ADDR_MAX SIZE_MAX

/*
 * Invalid information
 */
#define INVALID_ADDR ADDR_MAX
#define INVALID_FD -1
#define INVALID_SHM_ID -1
#define INVALID_PID 0

/*
 * Re-define type
 */
typedef size_t addr_t;
typedef void PhantomType;
typedef long double double128_t;

/*
 * XXX:
 *  + SHADOW_CODE_ADDR: random address based on ASLR/PIE
 *  + SIGNAL_STACK_ADDR: random address based on ASLR/PIE
 *  + RETADDR_MAPPING_ADDR: random address based on ASLR/PIE
 *  + LOOKUP_TABLE_ADDR: random address based on ASLR/PIE
 *  + RW_PAGE_ADDR: fixed address
 *  + AFL_MAP_ADDR: fixed address
 *  + CRS_MAP_ADDR: fixed address
 *
 * Note that, RW_PAGE_ADDR can only be fixed because we need it to access the
 * programb base on the runtime. On the contrary, AFL_MAP_ADDR and CRS_MAP_ADDR
 * should have not been fixed, but they indeed are mainly due to the keystone
 * bug that is related to address redirecting.
 */
// XXX: see http://ref.x86asm.net/coder64.html for x64 encoding
#define SHADOW_CODE_ADDR 0x1f1f8000

// XXX: SIGSTKSZ is now a run-time variable, which makes compilation of loader
// and forkserver failed.
// Check discussion below:
//  https://public-inbox.org/libc-alpha/87y2ew8i1w.fsf@igel.home/T/
// Some references:
//  https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/bits/sigstack.h.html#30
//  https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/bits/sigstksz.h.html#28
#ifndef SIGNAL_STACK_SIZE
#error "SIGNAL_STACK_SIZE should be determined before compilation"
#endif
// XXX: we pick a high address to avoid overflow with other important pages
#define SIGNAL_STACK_ADDR (0x100000000 + SIGNAL_STACK_SIZE)

#define RETADDR_MAPPING_ADDR (SIGNAL_STACK_ADDR + SIGNAL_STACK_SIZE)

/*
 * [RW_PAGE_ADDR] The meta information needed during loading
 */
// XXX: members with addr_t are runtime address (especially for PIE)
typedef struct __loading_info_t {
    addr_t program_base;

    uint64_t afl_prev_id;

    uint64_t client_pid;

    uint64_t prev_pc;

    char shadow_path[0x100];
    uint64_t shadow_size;
    addr_t shadow_base;

    char lookup_tab_path[0x100];
    uint64_t lookup_tab_size;
    addr_t lookup_tab_base;

    char pipe_path[0x100];

    char shared_text_path[0x100];
    uint64_t shared_text_size;
    addr_t shared_text_base;

    char retaddr_mapping_path[0x100];
    uint64_t retaddr_mapping_size;
    addr_t retaddr_mapping_base;
    bool retaddr_mapping_used;

    bool daemon_attached;

} __LoadingInfo;

#define RW_PAGE_ADDR 0x300000
#define RW_PAGE_SIZE PAGE_SIZE
#define RW_PAGE_USED_SIZE sizeof(__LoadingInfo)
#define RW_PAGE_INFO_ADDR(f) (RW_PAGE_ADDR + offsetof(__LoadingInfo, f))
#define RW_PAGE_INFO(field) (((__LoadingInfo *)RW_PAGE_ADDR)->field)

/*
 * Prefix and suffix for additional files
 */
#define TEMPFILE_NAME_PREFIX "." OURTOOL "."
#define LOOKUP_TABNAME_PREFIX ".lookup."
#define TRAMPOLINES_NAME_PREFIX ".shadow."
#define SHARED_TEXT_PREFIX ".text."
#define RETADDR_MAPPING_PREFIX ".ret."
#define CRASHPOINT_LOG_PREFIX ".crashpoint."
#define PIPE_FILENAME_PREFIX ".pipe."
#define PDISASM_FILENAME_PREFIX ".pdisasm."
#define METADATA_FILENAME_PREFIX ".meta."
#define CODE_SEGMENT_FILE_SUFFIX ".code.segments"
#define BACKUP_FILE_SUFFIX ".bak"
#define PATCHED_FILE_SUFFIX ".patch"
#define PHANTOM_FILE_SUFFIX ".phantom"

/*
 * Lookup table
 */
extern void z_lookup_table_init_cell_num(uint64_t text_size);
extern uint64_t z_lookup_table_get_cell_num();

#define LOOKUP_TABLE_INIT_CELL_NUM(x) z_lookup_table_init_cell_num(x)

#define LOOKUP_TABLE_CELL_SIZE_POW2 2
#define LOOKUP_TABLE_CELL_SIZE (1 << LOOKUP_TABLE_CELL_SIZE_POW2)
#define LOOKUP_TABLE_CELL_MASK ((1UL << (LOOKUP_TABLE_CELL_SIZE * 8)) - 1)
#define LOOKUP_TABLE_CELL_NUM z_lookup_table_get_cell_num()

#define LOOKUP_TABLE_SIZE (LOOKUP_TABLE_CELL_SIZE * LOOKUP_TABLE_CELL_NUM)

#define LOOKUP_TABLE_MAX_CELL_NUM 0x8000000
#define LOOKUP_TABLE_MAX_SIZE \
    (LOOKUP_TABLE_CELL_SIZE * LOOKUP_TABLE_MAX_CELL_NUM)

// in case of conflicting with asan shadow memory
#define LOOKUP_TABLE_ADDR ((0x7fff8000) - LOOKUP_TABLE_MAX_SIZE)

/*
 * Crash check
 */
// For exit code usage, check https://tldp.org/LDP/abs/html/exitcodes.html for
// more information.
// It is lucky that we can play with the high 16 bits of status.
#define __RS(s) ((s) & (0xffff))          // __REAL_STATUS
#define __SF(s) (!!((s) & (0xffff0000)))  // __SELF_FIRED
#define PACK_STATUS(s, r) ((((r) << 16) & (0xffff0000)) | (((s) & (0xffff))))
#define IS_SUSPECT_STATUS(s) \
    (__SF(s) && WIFSIGNALED(__RS(s)) && (WTERMSIG(__RS(s)) == SIGKILL))
#define IS_ABNORMAL_STATUS(s) \
    (__SF(s) || (!WIFEXITED(__RS(s)) && WIFSIGNALED(__RS(s))))
// XXX: AFL uses SIGKILL to terminate a timeouted process (same as us)
#define IS_TIMEOUT_STATUS(s) \
    (!__SF(s) && WIFSIGNALED(__RS(s)) && (WTERMSIG(__RS(s)) == SIGKILL))

/*
 * Define struct with type info
 */
typedef struct meta_struct_t {
    const char *__type;
} MetaStruct;

#define STRUCT(name, content) \
    typedef struct name##_t { \
        const char *__type;   \
        struct content;       \
    } name

#define STRUCT_REALNAME(type) struct type##_t

#define STRUCT_TYPE(var) ((MetaStruct *)var)->__type

#define STRUCT_ALLOC(type)                    \
    ({                                        \
        type *var = z_alloc(1, sizeof(type)); \
        var->__type = #type;                  \
        var;                                  \
    })

/*
 * Setter and Getter
 *      OTYPE: type of object (e.g., Binary)
 *      ONAME: name of object (e.g., binary)
 *      FTYPE: type of filed (e.g., Elf_Info *)
 *      FNAME: name of filed (e.g., elf)
 */
#define DECLARE_SETTER(OTYPE, ONAME, FTYPE, FNAME) \
    Z_API void z_##ONAME##_##set_##FNAME(OTYPE *ONAME, FTYPE FNAME)

#define DEFINE_SETTER(OTYPE, ONAME, FTYPE, FNAME)                     \
    Z_API void z_##ONAME##_##set_##FNAME(OTYPE *ONAME, FTYPE FNAME) { \
        assert(ONAME != NULL);                                        \
        ONAME->FNAME = FNAME;                                         \
    }

#define DECLARE_GETTER(OTYPE, ONAME, FTYPE, FNAME) \
    Z_API FTYPE z_##ONAME##_##get_##FNAME(OTYPE *ONAME)

#define DEFINE_GETTER(OTYPE, ONAME, FTYPE, FNAME)         \
    Z_API FTYPE z_##ONAME##_##get_##FNAME(OTYPE *ONAME) { \
        assert(ONAME != NULL);                            \
        return ONAME->FNAME;                              \
    }

#define OVERLOAD_SETTER(OTYPE, ONAME, FTYPE, FNAME) \
    Z_API void z_##ONAME##_##set_##FNAME(OTYPE *ONAME, FTYPE FNAME)

#define OVERLOAD_GETTER(OTYPE, ONAME, FTYPE, FNAME) \
    Z_API FTYPE z_##ONAME##_##get_##FNAME(OTYPE *ONAME)

#endif


================================================
FILE: src/core.c
================================================
/*
 * core.c
 * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "core.h"
#include "crs_config.h"
#include "elf_.h"
#include "utils.h"

#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

/*
 * System clean up
 */
static Core *__core = NULL;

// callback function for exit
static void __core_atexit(void) {
    if (__core) {
        z_core_destroy(__core);
    }
    system("rm -f " TEMPFILE_NAME_PREFIX "*");
}

// stop signal handling
static void __core_handle_stop_sig(int _sig_id) {
    __core_atexit();
    kill(getpid(), SIGKILL);
}

// timeout handling
static void __core_handle_timeout(int _sig_id) {
    if (__core && __core->client_pid != INVALID_PID) {
        z_warn("client timeout");
        kill(__core->client_pid, SIGKILL);
    }
}

// setup all signal handlers
static void __core_setup_signal_handlers(void) {
    struct sigaction sa;

    sa.sa_handler = NULL;
    sa.sa_flags = SA_RESTART;
    sa.sa_sigaction = NULL;

    sigemptyset(&sa.sa_mask);

    /* Various ways of saying "stop". */

    sa.sa_handler = __core_handle_stop_sig;
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    /* Exec timeout notifications. */

    sa.sa_handler = __core_handle_timeout;
    sigaction(SIGALRM, &sa, NULL);
}

// avoid duplicate setting (in case there are two instances of core)
static bool __core_signal_handled = false;

// setup environment needed by core
static void __core_environment_setup(void) {
    atexit(__core_atexit);
    if (!__core_signal_handled) {
        __core_setup_signal_handlers();
        __core_signal_handled = true;
    }
}

// clean cached files
static void __core_clean_cache(const char *pathname) {
#define __RM_CACHE(prefix, binary)                       \
    do {                                                 \
        const char *filename = z_strcat(prefix, binary); \
        if (!z_access(filename, F_OK)) {                 \
            if (remove(filename)) {                      \
                EXITME("failed to remove %s", filename); \
            }                                            \
        }                                                \
        z_free((void *)filename);                        \
    } while (0)

    __RM_CACHE(LOOKUP_TABNAME_PREFIX, pathname);
    __RM_CACHE(TRAMPOLINES_NAME_PREFIX, pathname);
    __RM_CACHE(SHARED_TEXT_PREFIX, pathname);
    __RM_CACHE(RETADDR_MAPPING_PREFIX, pathname);
    __RM_CACHE(CRASHPOINT_LOG_PREFIX, pathname);
    __RM_CACHE(PIPE_FILENAME_PREFIX, pathname);
    __RM_CACHE(PDISASM_FILENAME_PREFIX, pathname);
    __RM_CACHE(METADATA_FILENAME_PREFIX, pathname);

#undef __RM_CACHE
}

// check whether the binary and cached files are valid, and update the meta file
// if needed.
static void __core_check_binary(const char *pathname, RewritingOptArgs *opts) {
    // step 1. check pathname
    z_info("patch binary file: \"%s\"", pathname);
    if (z_strchr(pathname, '/')) {
        // TODO: it is a ugly approach to check working directory, change it
        // when possible
        EXITME("please make sure " OURTOOL
               " running under the same directory with the target bianry (no "
               "slash symbol).");
    }

    // step 2. collect metadate
    Buffer *binary_buf = z_buffer_read_file(pathname);
    GChecksum *checksum = g_checksum_new(G_CHECKSUM_MD5);
    g_checksum_update(checksum, z_buffer_get_raw_buf(binary_buf),
                      z_buffer_get_size(binary_buf));
    const char *checksum_str = g_checksum_get_string(checksum);
    z_info("MD5(%s) = %s", pathname, checksum_str);

    // step 3. check metadata if needed
    const char *metadata_filename =
        z_strcat(METADATA_FILENAME_PREFIX, pathname);
    if (!z_access(metadata_filename, F_OK)) {
        Buffer *metadata_buf = z_buffer_read_file(metadata_filename);
        size_t metadata_size = z_buffer_get_size(metadata_buf);
        const uint8_t *metadata = z_buffer_get_raw_buf(metadata_buf);

        if (metadata_size !=
            sizeof(RewritingOptArgs) + z_strlen(checksum_str) + 1) {
            z_info("inconsistent size of cache metadata, remove cached files");
            __core_clean_cache(pathname);
        } else if (memcmp(metadata, opts, sizeof(RewritingOptArgs))) {
            z_info("inconsistent rewriting options, remove cached files");
            __core_clean_cache(pathname);
        } else if (z_strcmp((const char *)metadata + sizeof(RewritingOptArgs),
                            checksum_str)) {
            z_info("inconsistent binaries, remove cached files");
            __core_clean_cache(pathname);
        }

        z_buffer_destroy(metadata_buf);
    }

    // step 4. update medadata file
    {
        Buffer *metadata_buf = z_buffer_create(NULL, 0);

        z_buffer_append_raw(metadata_buf, (const uint8_t *)opts,
                            sizeof(RewritingOptArgs));
        z_buffer_append_raw(metadata_buf, (const uint8
Download .txt
gitextract_uw9hr437/

├── .github/
│   └── workflows/
│       ├── basic.yml
│       ├── benchmark.yml
│       ├── early_instrumentation.yml
│       ├── force_linear.yml
│       ├── no_generic_pic.yml
│       └── pdisasm.yml
├── .gitignore
├── LICENSE
├── README.md
├── benchmark/
│   ├── boringssl-2016-02-12.inline
│   ├── boringssl-2016-02-12.normal
│   ├── boringssl-2016-02-12.seed
│   ├── c-ares-CVE-2016-5180.inline
│   ├── c-ares-CVE-2016-5180.normal
│   ├── c-ares-CVE-2016-5180.seed
│   ├── freetype2-2017.inline
│   ├── freetype2-2017.normal
│   ├── freetype2-2017.seed
│   ├── guetzli-2017-3-30.inline
│   ├── guetzli-2017-3-30.normal
│   ├── guetzli-2017-3-30.seed
│   ├── harfbuzz-1.3.2.inline
│   ├── harfbuzz-1.3.2.normal
│   ├── harfbuzz-1.3.2.seed
│   ├── json-2017-02-12.inline
│   ├── json-2017-02-12.normal
│   ├── json-2017-02-12.seed
│   ├── lcms-2017-03-21.inline
│   ├── lcms-2017-03-21.normal
│   ├── lcms-2017-03-21.seed
│   ├── libarchive-2017-01-04.inline
│   ├── libarchive-2017-01-04.normal
│   ├── libarchive-2017-01-04.seed
│   ├── libjpeg-turbo-07-2017.inline
│   ├── libjpeg-turbo-07-2017.normal
│   ├── libjpeg-turbo-07-2017.seed
│   ├── libpng-1.2.56.inline
│   ├── libpng-1.2.56.normal
│   ├── libpng-1.2.56.seed
│   ├── libssh-2017-1272.inline
│   ├── libssh-2017-1272.normal
│   ├── libssh-2017-1272.seed
│   ├── libxml2-v2.9.2.inline
│   ├── libxml2-v2.9.2.normal
│   ├── libxml2-v2.9.2.seed
│   ├── llvm-libcxxabi-2017-01-27.inline
│   ├── llvm-libcxxabi-2017-01-27.normal
│   ├── llvm-libcxxabi-2017-01-27.seed
│   ├── openssl-1.0.1f.inline
│   ├── openssl-1.0.1f.normal
│   ├── openssl-1.0.1f.seed
│   ├── openssl-1.0.2d.inline
│   ├── openssl-1.0.2d.normal
│   ├── openssl-1.0.2d.seed
│   ├── openssl-1.1.0c.inline
│   ├── openssl-1.1.0c.normal
│   ├── openssl-1.1.0c.seed
│   ├── openthread-2018-02-27.inline
│   ├── openthread-2018-02-27.normal
│   ├── openthread-2018-02-27.seed
│   ├── pcre2-10.00.inline
│   ├── pcre2-10.00.normal
│   ├── pcre2-10.00.seed
│   ├── proj4-2017-08-14.inline
│   ├── proj4-2017-08-14.normal
│   ├── proj4-2017-08-14.seed
│   ├── re2-2014-12-09.inline
│   ├── re2-2014-12-09.normal
│   ├── re2-2014-12-09.seed
│   ├── runtime/
│   │   ├── server.key
│   │   └── server.pem
│   ├── sqlite-2016-11-14.inline
│   ├── sqlite-2016-11-14.normal
│   ├── sqlite-2016-11-14.seed
│   ├── vorbis-2017-12-11.inline
│   ├── vorbis-2017-12-11.normal
│   ├── vorbis-2017-12-11.seed
│   ├── woff2-2016-05-06.inline
│   ├── woff2-2016-05-06.normal
│   ├── woff2-2016-05-06.seed
│   ├── wpantund-2018-02-27.inline
│   ├── wpantund-2018-02-27.normal
│   └── wpantund-2018-02-27.seed
├── build.sh
├── clean.sh
├── docs/
│   ├── system.md
│   ├── tips.md
│   ├── todo.md
│   └── trouble.md
├── scripts/
│   └── stochfuzz_env.sh
├── src/
│   ├── .clang-format
│   ├── Makefile
│   ├── address_dictionary.h
│   ├── afl_config.h
│   ├── asm_syscall.c
│   ├── asm_utils.c
│   ├── binary.c
│   ├── binary.h
│   ├── buffer.c
│   ├── buffer.h
│   ├── capstone_.c
│   ├── capstone_.h
│   ├── config.h
│   ├── core.c
│   ├── core.h
│   ├── crs_config.h
│   ├── diagnoser.c
│   ├── diagnoser.h
│   ├── disassembler.c
│   ├── disassembler.h
│   ├── elf_.c
│   ├── elf_.h
│   ├── fork_server.c
│   ├── fork_server.h
│   ├── frontend.c
│   ├── get_signal_stack_size.sh
│   ├── interval_splay.c
│   ├── interval_splay.h
│   ├── iterator.h
│   ├── library_functions/
│   │   ├── generate.py
│   │   ├── lib.csv
│   │   ├── library_functions.c
│   │   └── library_functions.h
│   ├── libstochfuzz.h
│   ├── libstochfuzzRT.c
│   ├── loader.c
│   ├── loader.h
│   ├── mem_file.c
│   ├── mem_file.h
│   ├── patcher.c
│   ├── patcher.h
│   ├── prob_disasm/
│   │   ├── prob_disasm_complete/
│   │   │   ├── dag.c
│   │   │   ├── hints.c
│   │   │   ├── propagation.c
│   │   │   └── solving.c
│   │   ├── prob_disasm_complete.c
│   │   └── prob_disasm_simple.c
│   ├── restricted_ptr.c
│   ├── restricted_ptr.h
│   ├── rewriter.c
│   ├── rewriter.h
│   ├── rewriter_handlers/
│   │   ├── generate.py
│   │   ├── handler_call.c
│   │   ├── handler_cjmp.c
│   │   ├── handler_jmp.c
│   │   ├── handler_loop.c
│   │   ├── handler_main.in
│   │   └── handler_ret.c
│   ├── sys_optarg.c
│   ├── sys_optarg.h
│   ├── tp_dispatcher.c
│   ├── tp_dispatcher.h
│   ├── trampolines/
│   │   ├── Makefile
│   │   ├── bitmap.c
│   │   ├── context_restore.c
│   │   ├── context_save.c
│   │   └── trampolines.h
│   ├── ucfg_analyzer.c
│   ├── ucfg_analyzer.h
│   ├── utils.c
│   ├── utils.h
│   └── x64_utils.c
└── test/
    ├── .crashpoint.z3
    ├── bzip2.no.pie
    ├── bzip2.pie
    ├── check_avx512
    ├── check_avx512.c
    ├── crash
    ├── crash.c
    ├── ex.smt2
    ├── hello
    ├── json-2017-02-12.normal
    ├── json.seed
    ├── leak-268f0e85f4bc45cbaf4d257222b830eac18977f3
    ├── libjpeg.asan
    ├── libpng-1.2.56
    ├── no_main
    ├── no_main.c
    ├── openssl-1.0.1f
    ├── openssl-1.0.1f.code.segments
    ├── pngfix.pie
    ├── rar
    ├── readelf.pie
    ├── runtime/
    │   ├── server.key
    │   └── server.pem
    ├── small_exec.elf
    ├── tcpdump.pie
    ├── test.c.bz2
    ├── test_daemon.sh
    ├── test_daemon_ignore_asan_sof.sh
    ├── timeout
    ├── timeout.c
    ├── unintentional_crash
    ├── unintentional_crash.c
    ├── vrrp.pcap
    └── z3
Download .txt
SYMBOL INDEX (419 symbols across 52 files)

FILE: src/asm_syscall.c
  type kernel_sigaction (line 46) | struct kernel_sigaction {
  type kernel_sigaction (line 176) | struct kernel_sigaction
  type kernel_sigaction (line 177) | struct kernel_sigaction
  type sockaddr (line 195) | struct sockaddr
  type stat (line 273) | struct stat
  type rusage (line 350) | struct rusage
  function Z_SYSCALL (line 383) | Z_SYSCALL pid_t sys_getpid() {
  function Z_SYSCALL (line 396) | Z_SYSCALL pid_t sys_fork() {
  function Z_SYSCALL (line 409) | Z_SYSCALL pid_t sys_pause() {

FILE: src/asm_utils.c
  function Z_UTILS (line 43) | Z_UTILS void __utils_puts(const char *s, bool newline) {
  function Z_UTILS (line 56) | Z_UTILS void utils_num2hexstr(char *s, uint64_t n) {
  function utils_hexstr2num (line 70) | Z_UTILS unsigned long utils_hexstr2num(const char **str_ptr) {
  function Z_UTILS (line 88) | Z_UTILS void utils_output_number(uint64_t n) {
  function Z_UTILS (line 95) | Z_UTILS void __utils_error(const char *err_str, bool need_exit) {
  function Z_UTILS (line 103) | Z_UTILS size_t utils_strcpy(char *dst, char *src) {
  type stat (line 146) | struct stat

FILE: src/binary.c
  function Z_PRIVATE (line 115) | Z_PRIVATE void __binary_align_trampolines_addr(Binary *b) {
  function Z_PRIVATE (line 119) | Z_PRIVATE void __binary_setup_loader(Binary *b) {
  function Z_PRIVATE (line 217) | Z_PRIVATE void __binary_setup_fork_server(Binary *b) {
  function Z_PRIVATE (line 287) | Z_PRIVATE void __binary_setup_lookup_table(Binary *b) {
  function Z_PRIVATE (line 291) | Z_PRIVATE void __binary_setup_retaddr_mapping(Binary *b) {
  function Z_PRIVATE (line 306) | Z_PRIVATE void __binary_setup_tp_zone(Binary *b) {
  function Z_API (line 317) | Z_API Binary *z_binary_open(const char *pathname, bool prior_fork_server) {
  function Z_API (line 347) | Z_API void z_binary_destroy(Binary *b) {
  function Z_API (line 357) | Z_API void z_binary_fsync(Binary *b) {
  function Z_API (line 362) | Z_API void z_binary_save(Binary *b, const char *pathname) {
  function Z_API (line 367) | Z_API void z_binary_create_snapshot(Binary *b, const char *pathname) {
  function Z_API (line 371) | Z_API void z_binary_insert_utp(Binary *b, addr_t utp_addr, const uint8_t...
  function Z_API (line 413) | Z_API addr_t z_binary_insert_shadow_code(Binary *b, const uint8_t *sc,
  function Z_API (line 423) | Z_API void z_binary_update_lookup_table(Binary *b, addr_t ori_addr,
  function Z_API (line 445) | Z_API bool z_binary_check_state(Binary *b, ELFState state) {
  function Z_API (line 449) | Z_API void z_binary_new_retaddr_entity(Binary *b, addr_t shadow_retaddr,

FILE: src/binary.h
  type addr_t (line 29) | typedef addr_t bb_t;

FILE: src/buffer.c
  function Z_PRIVATE (line 32) | Z_PRIVATE Buffer *__buffer_new(size_t size) {
  function Z_PRIVATE (line 59) | Z_PRIVATE void __buffer_extend(Buffer *buf, size_t new_chunk_size) {
  function Z_API (line 78) | Z_API Buffer *z_buffer_create(const uint8_t *ptr, size_t size) {
  function Z_API (line 91) | Z_API void z_buffer_push(Buffer *buf, uint8_t ch) {
  function Z_API (line 98) | Z_API void z_buffer_append(Buffer *dst, Buffer *src) {
  function Z_API (line 105) | Z_API void z_buffer_append_raw(Buffer *buf, const uint8_t *ptr, size_t s...
  function Z_API (line 114) | Z_API Buffer *z_buffer_read_file(const char *pathname) {
  function Z_API (line 139) | Z_API void z_buffer_write_file(Buffer *buf, const char *pathname) {
  function Z_API (line 154) | Z_API Buffer *z_buffer_dup(Buffer *src) {
  function Z_API (line 164) | Z_API void z_buffer_destroy(Buffer *buf) {
  function Z_API (line 175) | Z_API uint8_t *z_buffer_seek(Buffer *buf, size_t offset, int whence) {
  function Z_API (line 197) | Z_API size_t z_buffer_tell(Buffer *buf, const uint8_t *ptr, int whence) {
  function Z_API (line 219) | Z_API void z_buffer_truncate(Buffer *buf, size_t index) {
  function Z_API (line 229) | Z_API void z_buffer_fill(Buffer *buf, uint8_t ch, size_t size) {

FILE: src/capstone_.c
  function Z_PRIVATE (line 68) | Z_PRIVATE FLGState __capstone_mapping_flg_write(uint64_t flg_state) {
  function Z_PRIVATE (line 88) | Z_PRIVATE FLGState __capstone_mapping_flg_read(uint64_t flg_state) {
  function Z_PRIVATE (line 108) | Z_PRIVATE GPRState __capstone_mapping_pgr(x86_reg reg_id) {
  function Z_PRIVATE (line 159) | Z_PRIVATE GPRState __capstone_filter_pgr(x86_reg reg_id) {
  function Z_API (line 203) | Z_API bool z_capstone_is_call(const cs_insn *inst) {
  function Z_API (line 207) | Z_API bool z_capstone_is_jmp(const cs_insn *inst) {
  function Z_API (line 211) | Z_API bool z_capstone_is_xbegin(const cs_insn *inst) {
  function Z_API (line 215) | Z_API bool z_capstone_is_ret(const cs_insn *inst) {
  function Z_API (line 219) | Z_API bool z_capstone_is_loop(const cs_insn *inst) {
  function Z_API (line 229) | Z_API bool z_capstone_is_cjmp(const cs_insn *inst) {
  function Z_API (line 256) | Z_API bool z_capstone_is_terminator(const cs_insn *inst) {
  function Z_API (line 304) | Z_API bool z_capstone_is_rare(const cs_insn *inst) {
  function Z_API (line 322) | Z_API RegState *z_capstone_get_register_state(const cs_insn *inst) {
  function Z_API (line 421) | Z_API bool z_capstone_is_const_mem_ucall(const cs_insn *inst,
  function Z_API (line 449) | Z_API bool z_capstone_is_pc_related_ucall(const cs_insn *inst,
  function Z_API (line 477) | Z_API bool z_capstone_is_const_mem_ujmp(const cs_insn *inst, addr_t *add...
  function Z_API (line 504) | Z_API bool z_capstone_is_pc_related_ujmp(const cs_insn *inst,
  function Z_API (line 531) | Z_API void z_capstone_show_gpr_state(GPRState gpr_state) {
  function Z_API (line 543) | Z_API void z_capstone_show_flg_state(FLGState flg_state) {

FILE: src/capstone_.h
  type GPRState (line 54) | typedef enum gpr_state_t {
  type FLGState (line 87) | typedef enum flg_state_t {

FILE: src/config.h
  type addr_t (line 78) | typedef size_t addr_t;
  type PhantomType (line 79) | typedef void PhantomType;
  type double128_t (line 80) | typedef long double double128_t;
  type __LoadingInfo (line 119) | typedef struct __loading_info_t {
  type MetaStruct (line 216) | typedef struct meta_struct_t {

FILE: src/core.c
  function __core_atexit (line 38) | static void __core_atexit(void) {
  function __core_handle_stop_sig (line 46) | static void __core_handle_stop_sig(int _sig_id) {
  function __core_handle_timeout (line 52) | static void __core_handle_timeout(int _sig_id) {
  function __core_setup_signal_handlers (line 60) | static void __core_setup_signal_handlers(void) {
  function __core_environment_setup (line 86) | static void __core_environment_setup(void) {
  function __core_clean_cache (line 95) | static void __core_clean_cache(const char *pathname) {
  function __core_check_binary (line 121) | static void __core_check_binary(const char *pathname, RewritingOptArgs *...
  function Z_PRIVATE (line 191) | Z_PRIVATE uint32_t __afl_hash32(const void *key, uint32_t len, uint32_t ...
  function Z_PRIVATE (line 258) | Z_PRIVATE const char *__core_prepare_binary_under_curdir(const char *pat...
  function Z_PRIVATE (line 304) | Z_PRIVATE uint32_t __core_get_bitmap_hash(Core *core) {
  function Z_PRIVATE (line 313) | Z_PRIVATE void __core_set_client_clock(Core *core, pid_t client_pid) {
  function Z_PRIVATE (line 320) | Z_PRIVATE void __core_cancel_client_clock(Core *core, pid_t client_pid) {
  function Z_PRIVATE (line 330) | Z_PRIVATE void __core_setup_unix_domain_socket(Core *core) {
  function Z_PRIVATE (line 360) | Z_PRIVATE void __core_setup_shm(Core *core) {
  function Z_PRIVATE (line 380) | Z_PRIVATE void __core_setup_afl_shm(Core *core, int afl_shm_id) {
  function Z_PRIVATE (line 401) | Z_PRIVATE void __core_clean_environment(Core *core) {
  function Z_PUBLIC (line 422) | Z_PUBLIC int z_core_perform_dry_run(Core *core, int argc, const char **a...
  function Z_PUBLIC (line 582) | Z_PUBLIC Core *z_core_create(const char *pathname, SysOptArgs *opts) {
  function Z_PUBLIC (line 633) | Z_PUBLIC void z_core_activate(Core *core) {
  function Z_PUBLIC (line 645) | Z_PUBLIC void z_core_destroy(Core *core) {
  function Z_PUBLIC (line 665) | Z_PUBLIC void z_core_detach(Core *core) {
  function Z_PUBLIC (line 669) | Z_PUBLIC void z_core_attach(Core *core) {
  function Z_PUBLIC (line 673) | Z_PUBLIC void z_core_start_daemon(Core *core, int notify_fd) {

FILE: src/core.h
  type itimerval (line 50) | struct itimerval

FILE: src/crs_config.h
  type CRSStatus (line 27) | typedef enum crs_status_t {
  type __CRSInfo (line 38) | typedef struct __crs_info_t {

FILE: src/diagnoser.c
  function Z_PRIVATE (line 59) | Z_PRIVATE void __diagnoser_patch_crashpoint(Diagnoser *g, addr_t addr,
  function Z_PRIVATE (line 96) | Z_PRIVATE CPType __diagnoser_get_crashpoint_type(Diagnoser *g, addr_t addr,
  function Z_PRIVATE (line 121) | Z_PRIVATE addr_t __diagnoser_validate_crashpoint(Diagnoser *g, addr_t ad...
  function Z_PRIVATE (line 151) | Z_PRIVATE void __diagnoser_handle_single_crashpoint(Diagnoser *g, addr_t...
  function Z_PRIVATE (line 216) | Z_PRIVATE CRSStatus __diagnoser_delta_debug(Diagnoser *g, int status,
  function Z_API (line 444) | Z_API Diagnoser *z_diagnoser_create(Patcher *patcher, Rewriter *rewriter,
  function Z_API (line 468) | Z_API void z_diagnoser_destroy(Diagnoser *g) {
  function Z_API (line 474) | Z_API void z_diagnoser_read_crashpoint_log(Diagnoser *g) {
  function Z_API (line 492) | Z_API void z_diagnoser_write_crashpoint_log(Diagnoser *g) {
  function Z_API (line 527) | Z_API void z_diagnoser_apply_logged_crashpoints(Diagnoser *g) {
  function Z_API (line 574) | Z_API CRSStatus z_diagnoser_new_crashpoint(Diagnoser *g, int status,

FILE: src/diagnoser.h
  type CPType (line 43) | typedef enum cp_type_t {
  type CrashPoint (line 57) | typedef struct crash_point_t {
  type DDStage (line 71) | typedef enum delta_debugging_stage {

FILE: src/disassembler.c
  function Z_PRIVATE (line 73) | Z_PRIVATE void __disassembler_free_cs_insn(cs_insn *inst) { cs_free(inst...
  function __disassembler_pre_disasm (line 78) | void __disassembler_pre_disasm(Disassembler *d) {
  function Z_PRIVATE (line 173) | Z_PRIVATE bool __disassembler_has_inlined_data(Disassembler *d) {
  function Z_PRIVATE (line 191) | Z_PRIVATE bool __disassembler_analyze_inst(cs_insn *inst, addr_t *target...
  function Z_PRIVATE (line 218) | Z_PRIVATE void __disassembler_superset_disasm(Disassembler *d) {
  function Z_API (line 284) | Z_API Disassembler *z_disassembler_create(Binary *b, RewritingOptArgs *o...
  function Z_API (line 346) | Z_API void z_disassembler_destroy(Disassembler *d) {
  function Z_API (line 367) | Z_API void z_disassembler_get_prob_disasm_internal(
  function Z_API (line 376) | Z_API void z_disassembler_prob_disasm(Disassembler *d) {
  function Z_API (line 380) | Z_API double128_t z_disassembler_get_prob_disasm(Disassembler *d, addr_t...
  function Z_API (line 385) | Z_API void z_diassembler_update_prob_disasm(Disassembler *d, addr_t addr,
  function Z_API (line 392) | Z_API GQueue *z_disassembler_linear_disasm(Disassembler *d) {
  function Z_API (line 511) | Z_API GQueue *z_disassembler_recursive_disasm(Disassembler *d, addr_t ad...
  function Z_API (line 626) | Z_API const cs_insn *z_disassembler_update_superset_disasm(Disassembler *d,
  function Z_API (line 669) | Z_API cs_insn *z_disassembler_get_superset_disasm(Disassembler *d,
  function Z_API (line 702) | Z_API cs_insn *z_disassembler_get_recursive_disasm(Disassembler *d,
  function Z_API (line 708) | Z_API cs_insn *z_disassembler_get_linear_disasm(Disassembler *d, addr_t ...
  function Z_API (line 713) | Z_API bool z_disassembler_is_potential_block_entrypoint(Disassembler *d,
  function Z_API (line 718) | Z_API bool z_disassembler_is_potential_inst_entrypoint(Disassembler *d,
  function Z_API (line 723) | Z_API bool z_disassembler_is_within_disasm_range(Disassembler *d, addr_t...
  function Z_API (line 727) | Z_API Buffer *z_disassembler_get_occluded_addrs(Disassembler *d, addr_t ...
  function Z_API (line 762) | Z_API bool z_disassembler_fully_support_prob_disasm(Disassembler *d) {

FILE: src/elf_.c
  function Z_PRIVATE (line 131) | Z_PRIVATE FChunk *z_fchunk_create(_MEM_FILE *stream, size_t offset, size...
  function Z_PRIVATE (line 141) | Z_PRIVATE void z_fchunk_destroy(FChunk *fc) { z_free(fc); }
  function Z_PRIVATE (line 369) | Z_PRIVATE size_t __elf_stream_vaddr2off(ELF *e, addr_t addr) {
  function Z_PRIVATE (line 390) | Z_PRIVATE _MEM_FILE *__elf_open_file(ELF *e, const char *ori_filename) {
  function Z_PRIVATE (line 412) | Z_PRIVATE void *__elf_stream_off2ptr(_MEM_FILE *stream, size_t off) {
  function Z_PRIVATE (line 423) | Z_PRIVATE void __elf_rewrite_pt_note(ELF *e) {
  function Z_PRIVATE (line 439) | Z_PRIVATE void __elf_setup_pipe(ELF *e, const char *filename) {
  function Z_PRIVATE (line 448) | Z_PRIVATE void __elf_setup_retaddr_mapping(ELF *e, const char *filename) {
  function Z_PRIVATE (line 482) | Z_PRIVATE void __elf_setup_lookup_table(ELF *e, const char *filename) {
  function Z_PRIVATE (line 535) | Z_PRIVATE void __elf_setup_shared_text(ELF *e, const char *filename) {
  function Z_PRIVATE (line 582) | Z_PRIVATE void __elf_setup_trampolines(ELF *e, const char *filename) {
  function Z_PRIVATE (line 615) | Z_PRIVATE void __elf_extend_zones(ELF *e) {
  function Z_PRIVATE (line 665) | Z_PRIVATE Snode *__elf_find_segment_by_vaddr(ELF *e, addr_t vaddr) {
  function Z_PRIVATE (line 677) | Z_PRIVATE Elf64_Dyn *__elf_find_dyn_by_tag(ELF *e, Elf64_Xword tag) {
  function __elf_set_relro (line 698) | void __elf_set_relro(ELF *e) {
  function Z_PRIVATE (line 755) | Z_PRIVATE void __elf_parse_relocation(ELF *e) {
  function Z_PRIVATE (line 1036) | Z_PRIVATE void __elf_parse_shdr(ELF *e) {
  function Z_PRIVATE (line 1162) | Z_PRIVATE void __elf_parse_phdr(ELF *e) {
  function Z_PRIVATE (line 1212) | Z_PRIVATE void __elf_validate_header(_MEM_FILE *stream) {
  function Z_PRIVATE (line 1273) | Z_PRIVATE void __elf_set_virtual_mapping(ELF *e, const char *filename) {
  function Z_PRIVATE (line 1486) | Z_PRIVATE void __elf_parse_main(ELF *e) {
  function Z_API (line 1589) | Z_API ELF *z_elf_open(const char *ori_filename, bool detect_main) {
  function Z_API (line 1655) | Z_API Rptr *z_elf_vaddr2ptr(ELF *e, addr_t vaddr) {
  function Z_API (line 1684) | Z_API void z_elf_destroy(ELF *e) {
  function Z_API (line 1710) | Z_API void z_elf_fsync(ELF *e) {
  function Z_API (line 1719) | Z_API void z_elf_save(ELF *e, const char *pathname) {
  function Z_API (line 1741) | Z_API void z_elf_create_snapshot(ELF *e, const char *pathname) {
  function Z_API (line 1746) | Z_API size_t z_elf_read_all(ELF *e, addr_t addr, size_t n, void *buf) {
  function Z_API (line 1766) | Z_API size_t z_elf_read(ELF *e, addr_t addr, size_t n, void *buf) {
  function Z_API (line 1782) | Z_API size_t z_elf_write(ELF *e, addr_t addr, size_t n, const void *buf) {
  function Z_API (line 1869) | Z_API bool z_elf_check_region_free(ELF *e, Snode *region) {
  function Z_API (line 1874) | Z_API bool z_elf_insert_utp(ELF *e, Snode *utp, addr_t *mmap_addr,
  function Z_API (line 1910) | Z_API const LFuncInfo *z_elf_get_plt_info(ELF *e, addr_t addr) {
  function Z_API (line 1915) | Z_API const LFuncInfo *z_elf_get_got_info(ELF *e, addr_t addr) {
  function Z_API (line 1920) | Z_API bool z_elf_check_state(ELF *e, ELFState state) {
  function Z_API (line 1931) | Z_API bool z_elf_is_statically_linked(ELF *e) {

FILE: src/elf_.h
  type ELFState (line 34) | typedef enum elf_state_t {

FILE: src/fork_server.c
  function fork_server_atoi (line 281) | static inline int fork_server_atoi(char *s) {
  function fork_server_get_shm_id (line 303) | static inline int fork_server_get_shm_id(char **envp) {
  function fork_server_connect_pipe (line 327) | static inline int fork_server_connect_pipe() {
  function NO_INLINE (line 360) | NO_INLINE void fork_server_start(char **envp) {

FILE: src/fork_server.h
  type CRSLoopType (line 26) | typedef enum crs_loop_type {

FILE: src/frontend.c
  function usage (line 57) | static void usage(const char *argv0, int ret_status) {
  function parse_args (line 110) | static int parse_args(int argc, const char **argv) {
  function main (line 240) | int main(int argc, const char **argv) {
  function mode_patch (line 281) | static inline void mode_patch(int argc, const char **argv) {
  function mode_disasm (line 290) | static inline void mode_disasm(int argc, const char **argv) {
  function mode_view (line 302) | static inline void mode_view(int argc, const char **argv) {
  function mode_run (line 330) | static inline void mode_run(int argc, const char **argv) {
  function mode_start (line 353) | static inline void mode_start(int argc, const char **argv) {

FILE: src/interval_splay.c
  function Z_PRIVATE (line 76) | Z_PRIVATE void __splay_print_indented(Snode *root, int depth) {
  function Z_PRIVATE (line 92) | Z_PRIVATE void __splay_rotate(Snode **root, int direction) {
  function Z_PRIVATE (line 117) | Z_PRIVATE void __splay_link(Snode ***hook, int d, Snode *node) {
  function Z_PRIVATE (line 125) | Z_PRIVATE Snode *__splay(Snode **root, addr_t target) {
  function Z_PRIVATE (line 194) | Z_PRIVATE Buffer *__splay_sorted_list(Snode *root) {
  function Z_API (line 214) | Z_API Snode *z_snode_create(addr_t addr, size_t len, void *data,
  function Z_API (line 225) | Z_API void z_snode_destroy(Snode *node) {
  function Z_API (line 235) | Z_API Splay *z_splay_create(void *(*merge_fcn)(void *, void *)) {
  function Z_API (line 243) | Z_API void z_splay_destroy(Splay *splay) {
  function Z_API (line 254) | Z_API bool z_splay_interval_overlap(Splay *splay, Snode *node) {
  function Z_API (line 293) | Z_API Snode *z_splay_insert(Splay *splay, Snode *node) {
  function Z_API (line 355) | Z_API Snode *z_splay_delete(Splay *splay, addr_t addr) {
  function Z_API (line 391) | Z_API Snode *z_splay_search(Splay *splay, addr_t addr) {
  function Z_API (line 420) | Z_API inline Snode *z_splay_max(Splay *splay) {
  function Z_API (line 425) | Z_API inline Snode *z_splay_min(Splay *splay) {
  function Z_API (line 430) | Z_API Buffer *z_splay_sorted_list(Splay *splay) {
  function Z_API (line 437) | Z_API void z_splay_print(Splay *splay) {
  function Z_API (line 444) | Z_API void *z_direct_merge(void *_x, void *_y) { return NULL; }

FILE: src/library_functions/generate.py
  function generate_from_csv (line 14) | def generate_from_csv(filename):

FILE: src/library_functions/library_functions.c
  function Z_PRIVATE (line 40) | Z_PRIVATE LFuncInfo *__lfunc_info_create(const char *name, LCFGInfo cfg_...
  function Z_PRIVATE (line 49) | Z_PRIVATE void __lfunc_info_destroy(LFuncInfo *info) {
  function Z_API (line 59) | Z_API void z_libfunc_init() {
  function Z_API (line 71) | Z_API void z_libfunc_fini() {
  function Z_API (line 78) | Z_API const LFuncInfo *z_libfunc_get_info(const char *name) {
  function Z_API (line 98) | Z_API const LFuncInfo *z_libfunc_default() { return &default_func_info; }

FILE: src/library_functions/library_functions.h
  type LCFGInfo (line 25) | typedef enum lcfg_info_t {
  type LRAInfo (line 33) | typedef enum lra_info_t {
  type LFuncInfo (line 40) | typedef struct lfunc_info_t {

FILE: src/libstochfuzzRT.c
  type Retaddr (line 36) | typedef struct retaddr_entity_t {
  type RetaddrMapping (line 41) | typedef struct retaddr_mapping_t {
  function __runtime_mremap (line 47) | static void __runtime_mremap(const char* filename, void* addr, size_t le...
  function unw_word_t (line 81) | static unw_word_t __runtime_retaddr_translate(RetaddrMapping* mapping,
  function _ULx86_64_step (line 114) | int _ULx86_64_step(unw_cursor_t* cursor) {

FILE: src/loader.c
  function loader_mmap_fake_shared_memory (line 235) | static inline void loader_mmap_fake_shared_memory() {
  function loader_mmap_data_page (line 258) | static inline void loader_mmap_data_page(size_t rip_base) {
  function loader_catch_suspect_signals (line 271) | static void loader_catch_suspect_signals(int signal, siginfo_t *siginfo,
  function loader_set_signal_handler (line 328) | static inline void loader_set_signal_handler(addr_t rip_base) {
  function loader_set_seccomp (line 371) | static inline void loader_set_seccomp() {
  function NO_INLINE (line 434) | NO_INLINE void loader_load(Trampoline *tp, void *shared_text_base,
  function NO_INLINE (line 579) | NO_INLINE const char *loader_output_running_path(const char *pathname) {

FILE: src/loader.h
  type Trampoline (line 24) | typedef struct trampoline_t {

FILE: src/mem_file.c
  function Z_PRIVATE (line 57) | Z_PRIVATE void __mem_file_check_state(_MEM_FILE *stream) {
  function Z_PRIVATE (line 70) | Z_PRIVATE int __mem_file_stretch_to_size(_MEM_FILE *stream, size_t size) {
  function Z_PRIVATE (line 131) | Z_PRIVATE void __mem_file_open_stream(_MEM_FILE *stream, bool is_resumed) {
  function Z_API (line 158) | Z_API _MEM_FILE *z_mem_file_fopen(const char *pathname, const char *mode) {
  function Z_API (line 174) | Z_API void z_mem_file_fsync(_MEM_FILE *stream) {
  function Z_API (line 189) | Z_API void z_mem_file_fclose(_MEM_FILE *stream) {
  function Z_API (line 213) | Z_API size_t z_mem_file_pwrite(_MEM_FILE *stream, const void *buf, size_...
  function Z_API (line 241) | Z_API size_t z_mem_file_pread(_MEM_FILE *stream, void *buf, size_t count,
  function Z_API (line 255) | Z_API size_t z_mem_file_fwrite(void *ptr, size_t size, size_t nmemb,
  function Z_API (line 265) | Z_API void z_mem_file_fix_size(_MEM_FILE *stream, size_t size) {
  function Z_API (line 283) | Z_API size_t z_mem_file_fread(void *ptr, size_t size, size_t nmemb,
  function Z_API (line 293) | Z_API void z_mem_file_fseek(_MEM_FILE *stream, long offset, int whence) {
  function z_mem_file_ftell (line 309) | Z_API long z_mem_file_ftell(_MEM_FILE *stream) {
  function Z_API (line 317) | Z_API void z_mem_file_suspend(_MEM_FILE *stream) {
  function Z_API (line 346) | Z_API void z_mem_file_resume(_MEM_FILE *stream) {
  function Z_API (line 357) | Z_API void z_mem_file_save_as(_MEM_FILE *stream, const char *pathname) {

FILE: src/patcher.c
  type BridgePoint (line 34) | typedef struct bridge_point_t {
  function Z_PRIVATE (line 83) | Z_PRIVATE int32_t __patcher_compare_address(addr_t a, addr_t b, void *_d...
  function Z_PRIVATE (line 94) | Z_PRIVATE void __patcher_flip_uncertain_patch(Patcher *p, addr_t addr,
  function Z_PRIVATE (line 107) | Z_PRIVATE bool __patcher_patch_uncertain_address(Patcher *p, addr_t addr) {
  function Z_PRIVATE (line 129) | Z_PRIVATE bool __patcher_patch_certain_address(Patcher *p, addr_t addr,
  function Z_PRIVATE (line 156) | Z_PRIVATE void __patcher_bfs_certain_addresses(Patcher *p, addr_t addr) {
  function Z_PRIVATE (line 247) | Z_PRIVATE void __patcher_patch_all_F(Patcher *p) {
  function Z_PRIVATE (line 434) | Z_PRIVATE void __patcher_patch_all_F(Patcher *p) {
  function Z_PRIVATE (line 516) | Z_PRIVATE void __patcher_patch_all_S(Patcher *p) {
  function Z_API (line 550) | Z_API void z_patcher_describe(Patcher *p) {
  function Z_API (line 623) | Z_API Patcher *z_patcher_create(Disassembler *d, RewritingOptArgs *opts) {
  function Z_API (line 660) | Z_API void z_patcher_destroy(Patcher *p) {
  function Z_API (line 680) | Z_API void z_patcher_initially_patch(Patcher *p) {
  function Z_API (line 704) | Z_API PPType z_patcher_check_patchpoint(Patcher *p, addr_t addr) {
  function Z_API (line 772) | Z_API void z_patcher_build_bridge(Patcher *p, addr_t ori_addr,
  function Z_API (line 1232) | Z_API void z_patcher_bridge_stats(Patcher *p) {
  function Z_API (line 1239) | Z_API addr_t z_patcher_adjust_bridge_address(Patcher *p, addr_t addr) {
  function Z_API (line 1309) | Z_API size_t z_patcher_uncertain_patches_n(Patcher *p) {
  function Z_API (line 1317) | Z_API void z_patcher_self_correction_start(Patcher *p) {
  function Z_API (line 1329) | Z_API void z_patcher_self_correction_end(Patcher *p) {
  function Z_API (line 1381) | Z_API void z_patcher_flip_uncertain_patches(Patcher *p, bool is_s_iter,
  function Z_API (line 1445) | Z_API void z_patcher_unsafe_patch(Patcher *p, addr_t addr, size_t size,

FILE: src/patcher.h
  type PPType (line 35) | typedef enum patchpoint_type {

FILE: src/prob_disasm/prob_disasm_complete.c
  type DHintType (line 27) | typedef enum dynamic_hint_type_t {
  type DHint (line 33) | typedef struct dynamic_hint_t {
  function Z_PRIVATE (line 146) | Z_PRIVATE bool __double128_equal(double128_t a, double128_t b) {
  function Z_PRIVATE (line 154) | Z_PRIVATE double128_t __pow_in_4(double128_t base, size_t n) {
  function Z_PRIVATE (line 182) | Z_PRIVATE double128_t __pow_in_n(double128_t base, size_t n) {
  function __prob_disassembler_path_dfs (line 286) | bool __prob_disassembler_path_dfs(
  function __prob_disassembler_search_path (line 325) | void __prob_disassembler_search_path(ProbDisassembler *pd,
  function Z_PRIVATE (line 348) | Z_PRIVATE void __prob_disassembler_refresh_playground(ProbDisassembler *...
  function Z_PRIVATE (line 399) | Z_PRIVATE bool __prob_disassembler_get_propogate_successors(
  function Z_PRIVATE (line 431) | Z_PRIVATE double128_t z_prob_disassembler_get_inst_prob(ProbDisassembler...
  function Z_PRIVATE (line 461) | Z_PRIVATE void z_prob_disassembler_get_internal(
  function Z_PRIVATE (line 478) | Z_PRIVATE void z_prob_disassembler_update(ProbDisassembler *pd, addr_t a...
  function Z_PRIVATE (line 512) | Z_PRIVATE void z_prob_disassembler_start(ProbDisassembler *pd) {
  function Z_PRIVATE (line 585) | Z_PRIVATE ProbDisassembler *z_prob_disassembler_create(Disassembler *d) {
  function Z_PRIVATE (line 659) | Z_PRIVATE void z_prob_disassembler_destroy(ProbDisassembler *pd) {
  function Z_PRIVATE (line 709) | Z_PRIVATE void __disassembler_pdisasm_create(Disassembler *d) {
  function Z_PRIVATE (line 713) | Z_PRIVATE void __disassembler_pdisasm_destroy(Disassembler *d) {
  function Z_PRIVATE (line 717) | Z_PRIVATE void __disassembler_pdisasm_start(Disassembler *d) {
  function Z_PRIVATE (line 721) | Z_PRIVATE double128_t __disassembler_pdisasm_get_inst_prob(Disassembler *d,
  function Z_PRIVATE (line 726) | Z_PRIVATE void __disassembler_pdisasm_get_internal(
  function Z_PRIVATE (line 734) | Z_PRIVATE void __disassembler_pdisasm_update(Disassembler *d, addr_t addr,

FILE: src/prob_disasm/prob_disasm_complete/dag.c
  type TarjanInfo (line 22) | typedef struct tarjan_info_t {
  function Z_PRIVATE (line 41) | Z_PRIVATE void __prob_disassembler_tarjan(ProbDisassembler *pd,
  function Z_PRIVATE (line 113) | Z_PRIVATE void __prob_disassembler_build_dag(ProbDisassembler *pd) {

FILE: src/prob_disasm/prob_disasm_complete/hints.c
  type RegInfo (line 24) | typedef struct reg_info_t {
  function Z_PRIVATE (line 88) | Z_PRIVATE void __prob_disassembler_reg_hints_dfs(
  function Z_PRIVATE (line 134) | Z_PRIVATE void __prob_disassembler_collect_cf_hints(ProbDisassembler *pd) {
  function Z_PRIVATE (line 378) | Z_PRIVATE void __update_info_for_usedef_reg_hint(ProbDisassembler *pd,
  function Z_PRIVATE (line 407) | Z_PRIVATE void __update_info_for_killed_reg_hint(ProbDisassembler *pd,
  function Z_PRIVATE (line 442) | Z_PRIVATE void __prob_disassembler_collect_reg_hints(ProbDisassembler *p...
  function Z_PRIVATE (line 490) | Z_PRIVATE void __prob_disassembler_collect_pop_ret_hints(ProbDisassemble...
  function Z_PRIVATE (line 537) | Z_PRIVATE void __prob_disassembler_collect_str_hints(ProbDisassembler *p...
  function Z_PRIVATE (line 589) | Z_PRIVATE void __prob_disassembler_collect_value_hints(ProbDisassembler ...
  function Z_PRIVATE (line 675) | Z_PRIVATE void __prob_disassembler_collect_cmp_cjmp_hints(
  function Z_PRIVATE (line 734) | Z_PRIVATE void __prob_disassembler_collect_arg_call_hints(

FILE: src/prob_disasm/prob_disasm_complete/propagation.c
  function Z_PRIVATE (line 24) | Z_PRIVATE void __prob_disassembler_propogate_inst_hints(ProbDisassembler...

FILE: src/prob_disasm/prob_disasm_complete/solving.c
  function Z_PRIVATE (line 100) | Z_PRIVATE void __prob_disassembler_normalize_prob(ProbDisassembler *pd) {
  function Z_PRIVATE (line 169) | Z_PRIVATE void __prob_disassembler_restrain_prob(ProbDisassembler *pd) {
  function Z_PRIVATE (line 173) | Z_PRIVATE void __prob_disassembler_spread_hints(ProbDisassembler *pd) {

FILE: src/prob_disasm/prob_disasm_simple.c
  type CodeSegment (line 25) | typedef struct code_segment_t {
  function Z_PRIVATE (line 30) | Z_PRIVATE void __disassembler_pdisasm_create_S(Disassembler *d) {
  function Z_PRIVATE (line 92) | Z_PRIVATE void __disassembler_pdisasm_destroy_S(Disassembler *d) {
  function Z_PRIVATE (line 96) | Z_PRIVATE void __disassembler_pdisasm_start_S(Disassembler *d) {
  function Z_PRIVATE (line 102) | Z_PRIVATE double128_t __disassembler_pdisasm_get_inst_prob_S(Disassemble...
  function Z_PRIVATE (line 111) | Z_PRIVATE void __disassembler_pdisasm_get_internal_S(
  function Z_PRIVATE (line 118) | Z_PRIVATE void __disassembler_pdisasm_update_S(Disassembler *d, addr_t a...

FILE: src/restricted_ptr.c
  function Z_PRIVATE (line 27) | Z_PRIVATE void __rptr_check_null(Rptr *rptr) {
  function Z_API (line 33) | Z_API Rptr *z_rptr_create(uint8_t *base_ptr, size_t size) {
  function Z_API (line 41) | Z_API void z_rptr_destroy(Rptr *rptr) { z_free(rptr); }
  function Z_API (line 43) | Z_API void *z_rptr_safe_raw_ptr(Rptr *rptr, size_t n) {
  function Z_API (line 51) | Z_API void z_rptr_memcpy_to(Rptr *rptr, uint8_t *src, size_t size) {
  function Z_API (line 59) | Z_API void z_rptr_memcpy_from(Rptr *rptr, uint8_t *dst, size_t size) {
  function Z_API (line 67) | Z_API void z_rptr_truncate(Rptr *rptr, size_t n) {

FILE: src/rewriter.c
  function Z_PRIVATE (line 116) | Z_PRIVATE void __rewriter_count_conflicted_ids(Rewriter *r) {
  function Z_PRIVATE (line 144) | Z_PRIVATE void z_rewriter_rewrite_beyond_main(Rewriter *r) {
  function Z_PRIVATE (line 218) | Z_PRIVATE void z_rewriter_rewrite_entrypoint(Rewriter *r) {
  function Z_PRIVATE (line 231) | Z_PRIVATE void z_rewriter_rewrite_main(Rewriter *r) {
  function __rewriter_patch_utp (line 251) | bool __rewriter_patch_utp(Rewriter *r, addr_t ori_addr) {
  function addr_t (line 294) | addr_t __rewriter_calculate_utp_addr(Rewriter *r,
  function Z_PRIVATE (line 364) | Z_PRIVATE int __rewriter_compare_address(addr_t x, addr_t y, void *_z) {
  function Z_PRIVATE (line 373) | Z_PRIVATE void __rewriter_emit_trampoline(Rewriter *r, addr_t addr) {
  function Z_PRIVATE (line 417) | Z_PRIVATE void __rewriter_fillin_shadow_hole(Rewriter *r, GHashTable *ho...
  function Z_PRIVATE (line 472) | Z_PRIVATE cs_insn *__rewriter_translate_shadow_inst(Rewriter *r, cs_insn...
  function Z_PRIVATE (line 622) | Z_PRIVATE void __rewriter_generate_shadow_inst(Rewriter *r, GHashTable *...
  function Z_PRIVATE (line 774) | Z_PRIVATE void __rewriter_generate_shadow_block(
  function __rewriter_build_bridges (line 859) | void __rewriter_build_bridges(Rewriter *r,
  function Z_API (line 942) | Z_API Rewriter *z_rewriter_create(Disassembler *d, RewritingOptArgs *opt...
  function z_rewriter_heuristics_rewrite (line 990) | void z_rewriter_heuristics_rewrite(Rewriter *r) {
  function Z_API (line 1031) | Z_API void z_rewriter_destroy(Rewriter *r) {
  function Z_API (line 1053) | Z_API void z_rewriter_register_handler(Rewriter *r, REvent event,
  function Z_API (line 1059) | Z_API void z_rewriter_rewrite(Rewriter *r, addr_t new_addr) {
  function Z_API (line 1099) | Z_API void z_rewriter_optimization_stats(Rewriter *r) {
  function Z_API (line 1108) | Z_API addr_t z_rewriter_get_shadow_addr(Rewriter *r, addr_t addr) {
  function Z_API (line 1124) | Z_API bool z_rewriter_check_retaddr_crashpoint(Rewriter *r, addr_t addr) {
  function Z_API (line 1147) | Z_API Buffer *z_rewriter_new_validate_retaddr(Rewriter *r, addr_t retadd...
  function Z_API (line 1167) | Z_API void z_rewriter_initially_rewrite(Rewriter *r) {

FILE: src/rewriter_handlers/generate.py
  function extract_c_file (line 9) | def extract_c_file(c_file):
  function extend_buffer (line 33) | def extend_buffer(buffer, handlers):

FILE: src/rewriter_handlers/handler_call.c
  function Z_PRIVATE (line 47) | Z_PRIVATE const LFuncInfo *__rewriter_is_library_call(ELF *e, cs_insn *i...
  function Z_PRIVATE (line 75) | Z_PRIVATE void __rewriter_call_handler(Rewriter *r, GHashTable *holes,

FILE: src/rewriter_handlers/handler_cjmp.c
  function Z_PRIVATE (line 36) | Z_PRIVATE void __rewriter_cjmp_handler_for_rcx(Rewriter *r, GHashTable *...
  function Z_PRIVATE (line 116) | Z_PRIVATE bool __rewriter_cjmp_is_security_check(Rewriter *r, addr_t add...
  function Z_PRIVATE (line 148) | Z_PRIVATE void __rewriter_cjmp_handler(Rewriter *r, GHashTable *holes,

FILE: src/rewriter_handlers/handler_jmp.c
  function Z_PRIVATE (line 29) | Z_PRIVATE void __rewriter_jmp_handler(Rewriter *r, GHashTable *holes,

FILE: src/rewriter_handlers/handler_loop.c
  function Z_PRIVATE (line 29) | Z_PRIVATE void __rewriter_loop_handler(Rewriter *r, GHashTable *holes,

FILE: src/rewriter_handlers/handler_ret.c
  function Z_PRIVATE (line 29) | Z_PRIVATE void __rewriter_ret_handler(Rewriter *r, GHashTable *holes,

FILE: src/sys_optarg.h
  type SysMode (line 33) | typedef enum system_mode_t {
  type RewritingOptArgs (line 45) | typedef struct rewriting_optargs_t {
  type SysOptArgs (line 56) | typedef struct system_optargs_t {

FILE: src/tp_dispatcher.c
  function Z_PRIVATE (line 67) | Z_PRIVATE void __tp_code_destroy(TPCode *tpc) {
  function Z_PRIVATE (line 72) | Z_PRIVATE TPCode *__tp_code_create(size_t size) {
  function Z_PRIVATE (line 81) | Z_PRIVATE void __tp_code_locate_holes(TPCode *tpc, uint32_t id_hole,
  function Z_PRIVATE (line 90) | Z_PRIVATE void __tp_code_append_raw(TPCode *tpc, const uint8_t *buf,
  function Z_PRIVATE (line 99) | Z_PRIVATE const uint8_t *__tp_code_emit(TPCode *tpc, uint32_t id,
  function Z_API (line 109) | Z_API void z_tp_dispatcher_destroy(TPDispatcher *tpd) {
  function Z_API (line 119) | Z_API TPDispatcher *z_tp_dispatcher_create() {
  function Z_API (line 170) | Z_API const uint8_t *z_tp_dispatcher_emit_context_save(TPDispatcher *tpd,
  function Z_API (line 176) | Z_API const uint8_t *z_tp_dispatcher_emit_context_restore(TPDispatcher *...
  function Z_API (line 182) | Z_API const uint8_t *z_tp_dispatcher_emit_bitmap(TPDispatcher *tpd,

FILE: src/tp_dispatcher.h
  type TPCode (line 27) | typedef struct tp_code_t {

FILE: src/ucfg_analyzer.c
  type UEdge (line 29) | typedef enum ucfg_edge_t {
  function Z_PRIVATE (line 98) | Z_PRIVATE void __ucfg_analyzer_analyze_sec_chk(UCFG_Analyzer *a, addr_t ...
  function Z_PRIVATE (line 209) | Z_PRIVATE void __ucfg_analyzer_analyze_ret(UCFG_Analyzer *a, addr_t addr,
  function Z_PRIVATE (line 338) | Z_PRIVATE void __ucfg_analyzer_analyze_gpr(UCFG_Analyzer *a, addr_t addr,
  function Z_PRIVATE (line 463) | Z_PRIVATE void __ucfg_analyzer_analyze_flg(UCFG_Analyzer *a, addr_t addr,
  function Z_PRIVATE (line 605) | Z_PRIVATE void __ucfg_analyzer_advance_analyze(UCFG_Analyzer *a, addr_t ...
  function Z_PRIVATE (line 613) | Z_PRIVATE bool __ucfg_analyzer_check_consistent(const cs_insn *inst_alice,
  function Z_PRIVATE (line 684) | Z_PRIVATE void __ucfg_analyzer_new_pred_and_succ(UCFG_Analyzer *a,
  function Z_PRIVATE (line 743) | Z_PRIVATE void __ucfg_analyzer_init_analyze(UCFG_Analyzer *a, addr_t addr,
  function Z_API (line 812) | Z_API UCFG_Analyzer *z_ucfg_analyzer_create(Binary *binary,
  function Z_API (line 859) | Z_API void z_ucfg_analyzer_destroy(UCFG_Analyzer *a) {
  function Z_API (line 878) | Z_API void z_ucfg_analyzer_add_inst(UCFG_Analyzer *a, addr_t addr,
  function Z_API (line 914) | Z_API Buffer *z_ucfg_analyzer_get_direct_successors(UCFG_Analyzer *a,
  function Z_API (line 921) | Z_API Buffer *z_ucfg_analyzer_get_direct_predecessors(UCFG_Analyzer *a,
  function Z_API (line 928) | Z_API Buffer *z_ucfg_analyzer_get_intra_successors(UCFG_Analyzer *a,
  function Z_API (line 935) | Z_API Buffer *z_ucfg_analyzer_get_intra_predecessors(UCFG_Analyzer *a,
  function Z_API (line 942) | Z_API Buffer *z_ucfg_analyzer_get_all_successors(UCFG_Analyzer *a,
  function Z_API (line 949) | Z_API Buffer *z_ucfg_analyzer_get_all_predecessors(UCFG_Analyzer *a,
  function Z_API (line 956) | Z_API FLGState z_ucfg_analyzer_get_flg_need_write(UCFG_Analyzer *a,
  function Z_API (line 968) | Z_API GPRState z_ucfg_analyzer_get_gpr_can_write(UCFG_Analyzer *a,
  function Z_API (line 975) | Z_API RegState *z_ucfg_analyzer_get_register_state(UCFG_Analyzer *a,
  function Z_API (line 981) | Z_API bool z_ucfg_analyzer_is_security_chk_failed(UCFG_Analyzer *a,

FILE: src/utils.c
  function z_lookup_table_init_cell_num (line 32) | void z_lookup_table_init_cell_num(uint64_t text_size) {
  function z_lookup_table_get_cell_num (line 43) | uint64_t z_lookup_table_get_cell_num() {
  function Z_API (line 63) | Z_API void z_log_set_level(int level) { log_level = level; }
  function Z_API (line 65) | Z_API void z_log(int level, const char *file, int line, const char *fmt,...
  function Z_API (line 91) | Z_API int z_rand() {
  function Z_API (line 100) | Z_API void z_exit(int status) { exit(status); }
  function Z_API (line 102) | Z_API FILE *z_fopen(const char *pathname, const char *mode) {
  function Z_API (line 111) | Z_API void z_fclose(FILE *stream) {
  function Z_API (line 118) | Z_API void z_fseek(FILE *stream, long offset, int whence) {
  function z_ftell (line 125) | Z_API long z_ftell(FILE *stream) {
  function Z_API (line 134) | Z_API size_t z_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
  function Z_API (line 138) | Z_API size_t z_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream) {
  function Z_API (line 142) | Z_API int z_chmod(const char *pathname, mode_t mode) {
  function Z_API (line 146) | Z_API int z_access(const char *path, int mode) { return access(path, mod...
  function Z_API (line 148) | Z_API void *z_alloc(size_t nmemb, size_t size) {
  function Z_API (line 156) | Z_API void *z_realloc(void *ptr, size_t size) {
  function Z_API (line 164) | Z_API void z_free(void *ptr) { free(ptr); }
  function Z_API (line 169) | Z_API char *z_strcat(const char *s1, const char *s2) {
  function Z_API (line 177) | Z_API char *z_strstr(const char *haystack, const char *needle) {
  function Z_API (line 181) | Z_API char *z_strdup(const char *s) {
  function Z_API (line 188) | Z_API int z_strcmp(const char *s1, const char *s2) { return strcmp(s1, s...
  function Z_API (line 190) | Z_API int z_strncmp(const char *s1, const char *s2, size_t n) {
  function Z_API (line 194) | Z_API size_t z_strlen(const char *s) { return strlen(s); }
  function Z_API (line 196) | Z_API void z_strcpy(char *dst, const char *src) { strcpy(dst, src); }
  function Z_API (line 198) | Z_API char *z_strchr(const char *s, int c) { return strchr(s, c); }
  function Z_API (line 200) | Z_API char *z_strrchr(const char *s, int c) { return strrchr(s, c); }

FILE: src/x64_utils.c
  function Z_PRIVATE (line 25) | Z_PRIVATE const uint8_t *z_x64_gen_nop(size_t n) {
  function Z_PRIVATE (line 52) | Z_PRIVATE const uint8_t *z_x64_gen_invalid(size_t n) {

FILE: test/crash.c
  function main (line 4) | int main(int argc, const char **argv) {

FILE: test/timeout.c
  function my_sleep (line 4) | static void my_sleep() {
  function main (line 8) | int main(int argc, const char **argv) {

FILE: test/unintentional_crash.c
  function main (line 3) | int main(int argc, char **argv) {
Condensed preview — 196 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (934K chars).
[
  {
    "path": ".github/workflows/basic.yml",
    "chars": 2221,
    "preview": "name: basic\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    - cron: 0 14 "
  },
  {
    "path": ".github/workflows/benchmark.yml",
    "chars": 2262,
    "preview": "name: benchmark\n\non:\n  push:\n    branches:\n      - \"!*\"\n    tags:\n      - \"v*\"\n  schedule:\n    - cron: 0 14 * * 1\n  work"
  },
  {
    "path": ".github/workflows/early_instrumentation.yml",
    "chars": 2273,
    "preview": "name: early_instrumentation\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n "
  },
  {
    "path": ".github/workflows/force_linear.yml",
    "chars": 2264,
    "preview": "name: force_linear\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    - cron"
  },
  {
    "path": ".github/workflows/no_generic_pic.yml",
    "chars": 2266,
    "preview": "name: no_generic_pic\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    - cr"
  },
  {
    "path": ".github/workflows/pdisasm.yml",
    "chars": 1599,
    "preview": "name: pdisasm\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    - cron: 0 1"
  },
  {
    "path": ".gitignore",
    "chars": 1394,
    "preview": "# Prerequisites\n*.d\n\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n\n# Linker output\n*.ilk\n*.map\n*.exp\n\n# Precompiled Headers\n*.gch"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 8671,
    "preview": "# StochFuzz: A New Solution for Binary-only Fuzzing <a href=\"https://openai.com/product/dall-e-2\"><img src=\"imgs/logo.pn"
  },
  {
    "path": "benchmark/json-2017-02-12.seed",
    "chars": 14,
    "preview": "10000000010E5\n"
  },
  {
    "path": "benchmark/llvm-libcxxabi-2017-01-27.seed",
    "chars": 18,
    "preview": "ZUlSaIJT_2_EET_E5\n"
  },
  {
    "path": "benchmark/pcre2-10.00.seed",
    "chars": 1631,
    "preview": "# This is a specialized test for checking, when PCRE2 is compiled with the\n# EBCDIC option but in an ASCII environment, "
  },
  {
    "path": "benchmark/runtime/server.key",
    "chars": 522,
    "preview": "-----BEGIN PRIVATE KEY-----\nMIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA1AdZNDVOA9cXm97f\nerp1bukz2kohjToJS6Ma8fOb36V"
  },
  {
    "path": "benchmark/runtime/server.pem",
    "chars": 538,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBYTCCAQugAwIBAgIJAMPQQtUHkx+KMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNV\nBAMMAWEwHhcNMTYwOTI0MjIyMDU"
  },
  {
    "path": "benchmark/sqlite-2016-11-14.seed",
    "chars": 2712,
    "preview": " SELECT 888<8888888 | daDROPme(1,1 \n,11,1 \n,1)| 388<8888888 | datetime(1,1 ,11,1 \n,1)| 388<8888888 | datetime(1,1 \n,1)|8"
  },
  {
    "path": "benchmark/wpantund-2018-02-27.seed",
    "chars": 69,
    "preview": "0ConfiG:NCP:SocketPath \"/dev/null\"\nConfig:NCP:SocketPath \"/dev/null\"\n"
  },
  {
    "path": "build.sh",
    "chars": 3468,
    "preview": "#!/bin/bash\n\nRED=\"\\033[31m\"\nGREEN=\"\\033[32m\"\nYELLOW=\"\\033[33m\"\nBOLD=\"\\033[1m\"\nOFF=\"\\033[0m\"\n\nCAPSTONE_VERSION=\"4.0.2\"\nKE"
  },
  {
    "path": "clean.sh",
    "chars": 234,
    "preview": "#!/bin/bash\n\nif [ -d capstone ]\nthen\n    rm -rf capstone\nfi\n\nif [ -d keystone ]\nthen\n    rm -rf keystone\nfi\n\nif [ -d gli"
  },
  {
    "path": "docs/system.md",
    "chars": 6207,
    "preview": "# New System Design\n\nOriginally, StochFuzz was integrated into AFL, which made an easy development. However, as more and"
  },
  {
    "path": "docs/tips.md",
    "chars": 4393,
    "preview": "# Tips\n\nTo enable a more effective and efficient fuzzing, we provide several tips about better using StochFuzz. \n\n## Adv"
  },
  {
    "path": "docs/todo.md",
    "chars": 6775,
    "preview": "# Development Plan\n\n## Todo List\n\nWhile we have successfully migrated StochFuzz to a new system design, we can still imp"
  },
  {
    "path": "docs/trouble.md",
    "chars": 3286,
    "preview": "# Troubleshootings\n\nIf you are using a variant of AFL instead of the original [AFL](https://github.com/google/AFL), plea"
  },
  {
    "path": "scripts/stochfuzz_env.sh",
    "chars": 462,
    "preview": "#!/bin/bash\n\nstochfuzz_dir=$(realpath $(dirname \"$(realpath $0)\")/../)\nlibstochfuzzRT_path=\"$stochfuzz_dir/src/libstochf"
  },
  {
    "path": "src/.clang-format",
    "chars": 220,
    "preview": "BasedOnStyle: Google\nIndentWidth: 4\nAlwaysBreakTemplateDeclarations: true\nColumnLimit: 80\nUseTab: Never\nAllowShortIfStat"
  },
  {
    "path": "src/Makefile",
    "chars": 11397,
    "preview": "CC = clang\n\nSIGSTKSZ =  $(shell ./get_signal_stack_size.sh)\nCFLAGS = -Wall -Wno-unused-command-line-argument -Wno-void-p"
  },
  {
    "path": "src/address_dictionary.h",
    "chars": 8303,
    "preview": "/*\n * address_dictionary.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can "
  },
  {
    "path": "src/afl_config.h",
    "chars": 1734,
    "preview": "/*\n * afl_config.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistri"
  },
  {
    "path": "src/asm_syscall.c",
    "chars": 13430,
    "preview": "/*\n * asm_syscall.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistr"
  },
  {
    "path": "src/asm_utils.c",
    "chars": 4680,
    "preview": "/*\n * asm_utils.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistrib"
  },
  {
    "path": "src/binary.c",
    "chars": 16581,
    "preview": "/*\n * binary.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/binary.h",
    "chars": 4454,
    "preview": "/*\n * binary.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/buffer.c",
    "chars": 6936,
    "preview": "/*\n * buffer.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/buffer.h",
    "chars": 2521,
    "preview": "/*\n * buffer.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/capstone_.c",
    "chars": 16453,
    "preview": "/*\n * capstone_.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistrib"
  },
  {
    "path": "src/capstone_.h",
    "chars": 6180,
    "preview": "/*\n * capstone_.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistrib"
  },
  {
    "path": "src/config.h",
    "chars": 8274,
    "preview": "/*\n * config.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/core.c",
    "chars": 30549,
    "preview": "/*\n * core.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute i"
  },
  {
    "path": "src/core.h",
    "chars": 2217,
    "preview": "/*\n * core.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute i"
  },
  {
    "path": "src/crs_config.h",
    "chars": 1969,
    "preview": "/*\n * crs_config.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistri"
  },
  {
    "path": "src/diagnoser.c",
    "chars": 24675,
    "preview": "/*\n * diagnoser.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistrib"
  },
  {
    "path": "src/diagnoser.h",
    "chars": 4208,
    "preview": "/*\n * diagnoser.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistrib"
  },
  {
    "path": "src/disassembler.c",
    "chars": 28571,
    "preview": "/*\n * disassembler.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/disassembler.h",
    "chars": 5963,
    "preview": "/*\n * disassembler.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/elf_.c",
    "chars": 66087,
    "preview": "/*\n * __elf_parse_relocation in elf_.c\n *\n * URL: https://github.com/kubo/plthook\n *\n * --------------------------------"
  },
  {
    "path": "src/elf_.h",
    "chars": 10661,
    "preview": "/*\n * elf_.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute i"
  },
  {
    "path": "src/fork_server.c",
    "chars": 28066,
    "preview": "/*\n * the code inside asm(\".globl _entry\\n ...\")\n * Copyright (C) 2021 National University of Singapore\n * Copyright (C)"
  },
  {
    "path": "src/fork_server.h",
    "chars": 1064,
    "preview": "/*\n * fork_server.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistr"
  },
  {
    "path": "src/frontend.c",
    "chars": 11289,
    "preview": "/*\n * frontend.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribu"
  },
  {
    "path": "src/get_signal_stack_size.sh",
    "chars": 315,
    "preview": "#!/bin/bash\n\necho \"\n#include <signal.h>\n#include <stdio.h>\n\nint main(int argc, char **argv) {\n        int sz = SIGSTKSZ;"
  },
  {
    "path": "src/interval_splay.c",
    "chars": 12483,
    "preview": "/*\n * interval_splay.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redi"
  },
  {
    "path": "src/interval_splay.h",
    "chars": 3722,
    "preview": "/*\n * interval_splay.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redi"
  },
  {
    "path": "src/iterator.h",
    "chars": 2790,
    "preview": "/*\n * iterator.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribu"
  },
  {
    "path": "src/library_functions/generate.py",
    "chars": 1630,
    "preview": "import csv\nimport os\nimport sys\n\ntemplate = \"\"\"\nZ_PRIVATE void __libfunc_load(GHashTable *d) {\n%s\n}\n\"\"\"\n\nfilename = \"lib"
  },
  {
    "path": "src/library_functions/lib.csv",
    "chars": 27408,
    "preview": ",abort,TERM,USED\n,accept,RET,UNUSED\n,access,RET,UNUSED\n,acos,RET,UNUSED\n,__acosf_finite,,\n,alarm,RET,USED\n,archive_read_"
  },
  {
    "path": "src/library_functions/library_functions.c",
    "chars": 2590,
    "preview": "/*\n * library_functions.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can r"
  },
  {
    "path": "src/library_functions/library_functions.h",
    "chars": 1505,
    "preview": "/*\n * library_functions.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can r"
  },
  {
    "path": "src/libstochfuzz.h",
    "chars": 819,
    "preview": "/*\n * libstochfuzz.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/libstochfuzzRT.c",
    "chars": 5185,
    "preview": "/*\n * libstochfuzzRT.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redi"
  },
  {
    "path": "src/loader.c",
    "chars": 20537,
    "preview": "/*\n * the code inside asm(\".globl _entry\\n ...\")\n * Copyright (C) 2021 National University of Singapore\n * Copyright (C)"
  },
  {
    "path": "src/loader.h",
    "chars": 987,
    "preview": "/*\n * loader.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/mem_file.c",
    "chars": 11628,
    "preview": "/*\n * mem_file.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribu"
  },
  {
    "path": "src/mem_file.h",
    "chars": 3016,
    "preview": "/*\n * mem_file.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribu"
  },
  {
    "path": "src/patcher.c",
    "chars": 53101,
    "preview": "/*\n * patcher.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribut"
  },
  {
    "path": "src/patcher.h",
    "chars": 6351,
    "preview": "/*\n * patcher.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribut"
  },
  {
    "path": "src/prob_disasm/prob_disasm_complete/dag.c",
    "chars": 11777,
    "preview": "/*\n * dag.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute it"
  },
  {
    "path": "src/prob_disasm/prob_disasm_complete/hints.c",
    "chars": 31975,
    "preview": "/*\n * hints.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute "
  },
  {
    "path": "src/prob_disasm/prob_disasm_complete/propagation.c",
    "chars": 5988,
    "preview": "/*\n * propagation.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistr"
  },
  {
    "path": "src/prob_disasm/prob_disasm_complete/solving.c",
    "chars": 10447,
    "preview": "/*\n * solving.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribut"
  },
  {
    "path": "src/prob_disasm/prob_disasm_complete.c",
    "chars": 24843,
    "preview": "/*\n * prob_disasm_complete.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you ca"
  },
  {
    "path": "src/prob_disasm/prob_disasm_simple.c",
    "chars": 4358,
    "preview": "/*\n * prob_disasm_simple.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can "
  },
  {
    "path": "src/restricted_ptr.c",
    "chars": 2123,
    "preview": "/*\n * restricted_ptr.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redi"
  },
  {
    "path": "src/restricted_ptr.h",
    "chars": 3409,
    "preview": "/*\n * restricted_ptr.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redi"
  },
  {
    "path": "src/rewriter.c",
    "chars": 43555,
    "preview": "/*\n * rewriter.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribu"
  },
  {
    "path": "src/rewriter.h",
    "chars": 4040,
    "preview": "/*\n * rewriter.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribu"
  },
  {
    "path": "src/rewriter_handlers/generate.py",
    "chars": 2157,
    "preview": "import sys\nimport os\nimport re\n\nevent_re = re.compile(r\"\\s*#define\\s*REVENT\\s*(?P<event>\\S*)\\s*\")\nhandler_re = re.compil"
  },
  {
    "path": "src/rewriter_handlers/handler_call.c",
    "chars": 19074,
    "preview": "/*\n * handler_call.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/rewriter_handlers/handler_cjmp.c",
    "chars": 7890,
    "preview": "/*\n * handler_cjmp.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/rewriter_handlers/handler_jmp.c",
    "chars": 11300,
    "preview": "/*\n * handler_jmp.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistr"
  },
  {
    "path": "src/rewriter_handlers/handler_loop.c",
    "chars": 3300,
    "preview": "/*\n * handler_loop.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/rewriter_handlers/handler_main.in",
    "chars": 2404,
    "preview": "/*\n * handler_main.in\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redis"
  },
  {
    "path": "src/rewriter_handlers/handler_ret.c",
    "chars": 4985,
    "preview": "/*\n * handler_ret.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistr"
  },
  {
    "path": "src/sys_optarg.c",
    "chars": 1227,
    "preview": "/*\n * sys_optarg.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistri"
  },
  {
    "path": "src/sys_optarg.h",
    "chars": 1556,
    "preview": "/*\n * sys_optarg.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistri"
  },
  {
    "path": "src/tp_dispatcher.c",
    "chars": 6987,
    "preview": "/*\n * tp_dispatcher.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redis"
  },
  {
    "path": "src/tp_dispatcher.h",
    "chars": 2393,
    "preview": "/*\n * tp_dispatcher.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redis"
  },
  {
    "path": "src/trampolines/Makefile",
    "chars": 1425,
    "preview": "SIGSTKSZ =  $(shell ../get_signal_stack_size.sh)\n\nall: bitmap context_save context_restore\n\nbitmap:\n\t$(CC) -Wall -fno-st"
  },
  {
    "path": "src/trampolines/bitmap.c",
    "chars": 2847,
    "preview": "/*\n * bitmap.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute"
  },
  {
    "path": "src/trampolines/context_restore.c",
    "chars": 1618,
    "preview": "/*\n * context_restor.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redi"
  },
  {
    "path": "src/trampolines/context_save.c",
    "chars": 1608,
    "preview": "/*\n * context_save.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redist"
  },
  {
    "path": "src/trampolines/trampolines.h",
    "chars": 898,
    "preview": "/*\n * trampolines.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistr"
  },
  {
    "path": "src/ucfg_analyzer.c",
    "chars": 40515,
    "preview": "/*\n * ucfg_analyzer.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redis"
  },
  {
    "path": "src/ucfg_analyzer.h",
    "chars": 4915,
    "preview": "/*\n * ucfg_analyzer.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redis"
  },
  {
    "path": "src/utils.c",
    "chars": 5787,
    "preview": "/*\n * utils.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute "
  },
  {
    "path": "src/utils.h",
    "chars": 16211,
    "preview": "/*\n * utils.h\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistribute "
  },
  {
    "path": "src/x64_utils.c",
    "chars": 2114,
    "preview": "/*\n * x64_utils.c\n * Copyright (C) 2021 Zhuo Zhang, Xiangyu Zhang\n *\n * This program is free software: you can redistrib"
  },
  {
    "path": "test/check_avx512.c",
    "chars": 787,
    "preview": "/*\n * Check whether current CPU support AVX512. To compile, use following command:\n *\n *      clang -mavx512f check_avx5"
  },
  {
    "path": "test/crash.c",
    "chars": 180,
    "preview": "#include <stdio.h>\n#include <string.h>\n\nint main(int argc, const char **argv) {\n    if (argc > 1 && !strcmp(argv[1], \"md"
  },
  {
    "path": "test/ex.smt2",
    "chars": 31928,
    "preview": "; Boogie universal background predicate\n; Copyright (c) 2004-2010, Microsoft Corp.\n(set-info :category \"industrial\")\n(de"
  },
  {
    "path": "test/json.seed",
    "chars": 14,
    "preview": "1000000 010E5\n"
  },
  {
    "path": "test/no_main.c",
    "chars": 7814,
    "preview": "#define ASMSTR(S) \"\\t\" S \"\\n\"\n\nasm(\n    \".globl _entry\\n\"\n    \".type _entry,@function\\n\"\n    \"_entry:\\n\"\n\n    ASMSTR(\".i"
  },
  {
    "path": "test/runtime/server.key",
    "chars": 522,
    "preview": "-----BEGIN PRIVATE KEY-----\nMIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA1AdZNDVOA9cXm97f\nerp1bukz2kohjToJS6Ma8fOb36V"
  },
  {
    "path": "test/runtime/server.pem",
    "chars": 538,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBYTCCAQugAwIBAgIJAMPQQtUHkx+KMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNV\nBAMMAWEwHhcNMTYwOTI0MjIyMDU"
  },
  {
    "path": "test/test_daemon.sh",
    "chars": 739,
    "preview": "#!/bin/bash\n\nreadonly EXIT_FAILURE=1\n\ntool=$1\noptions=$2\ntarget=$3\nphantom=$target.phantom\necho \"phantom file: $phantom\""
  },
  {
    "path": "test/test_daemon_ignore_asan_sof.sh",
    "chars": 788,
    "preview": "#!/bin/bash\n\nreadonly EXIT_FAILURE=1\n\ntool=$1\noptions=$2\ntarget=$3\nphantom=$target.phantom\necho \"phantom file: $phantom\""
  },
  {
    "path": "test/timeout.c",
    "chars": 228,
    "preview": "#include <string.h>\n#include <unistd.h>\n\nstatic void my_sleep() {\n    sleep(5);\n}\n\nint main(int argc, const char **argv)"
  },
  {
    "path": "test/unintentional_crash.c",
    "chars": 9067,
    "preview": "#define ASMSTR(S) \"\\t\" S \"\\n\"\n\nint main(int argc, char **argv) {\n    asm volatile(\n        ASMSTR(\".intel_syntax noprefi"
  }
]

// ... and 90 more files (download for full content)

About this extraction

This page contains the full source code of the ZhangZhuoSJTU/StochFuzz GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 196 files (20.4 MB), approximately 240.6k tokens, and a symbol index with 419 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!