Full Code of angr/pyvex for AI

master 36455aaaf276 cached
80 files
387.1 KB
119.8k tokens
738 symbols
1 requests
Download .txt
Showing preview only (410K chars total). Download the full file or copy to clipboard to get everything.
Repository: angr/pyvex
Branch: master
Commit: 36455aaaf276
Files: 80
Total size: 387.1 KB

Directory structure:
gitextract_782bwflj/

├── .git-blame-ignore-revs
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   ├── config.yml
│   │   ├── feature-request.yml
│   │   └── question.yml
│   └── workflows/
│       ├── ci.yml
│       ├── cifuzz.yml
│       └── nightly-ci.yml
├── .gitignore
├── .gitmodules
├── .pre-commit-config.yaml
├── .readthedocs.yml
├── CMakeLists.txt
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs/
│   ├── Makefile
│   ├── api.rst
│   ├── conf.py
│   ├── index.rst
│   ├── make.bat
│   └── quickstart.rst
├── fuzzing/
│   ├── build.sh
│   ├── enhanced_fdp.py
│   └── irsb_fuzzer.py
├── make_ffi.py
├── pyproject.toml
├── pyvex/
│   ├── __init__.py
│   ├── _register_info.py
│   ├── arches.py
│   ├── block.py
│   ├── const.py
│   ├── const_val.py
│   ├── data_ref.py
│   ├── enums.py
│   ├── errors.py
│   ├── expr.py
│   ├── lifting/
│   │   ├── __init__.py
│   │   ├── gym/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── aarch64_spotter.py
│   │   │   ├── arm_spotter.py
│   │   │   └── x86_spotter.py
│   │   ├── libvex.py
│   │   ├── lift_function.py
│   │   ├── lifter.py
│   │   ├── post_processor.py
│   │   ├── util/
│   │   │   ├── __init__.py
│   │   │   ├── instr_helper.py
│   │   │   ├── lifter_helper.py
│   │   │   ├── syntax_wrapper.py
│   │   │   └── vex_helper.py
│   │   └── zerodivision.py
│   ├── native.py
│   ├── py.typed
│   ├── stmt.py
│   ├── types.py
│   └── utils.py
├── pyvex_c/
│   ├── LICENSE
│   ├── README
│   ├── analysis.c
│   ├── e4c_lite.h
│   ├── logging.c
│   ├── logging.h
│   ├── postprocess.c
│   ├── pyvex.c
│   ├── pyvex.def
│   ├── pyvex.h
│   └── pyvex_internal.h
└── tests/
    ├── test_arm_postprocess.py
    ├── test_gym.py
    ├── test_irsb_property_caching.py
    ├── test_lift.py
    ├── test_mips32_postprocess.py
    ├── test_pyvex.py
    ├── test_s390x_exrl.py
    ├── test_s390x_lochi.py
    ├── test_s390x_vl.py
    ├── test_spotter.py
    └── test_ud2.py

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

================================================
FILE: .git-blame-ignore-revs
================================================
# Black + pre-commit
23503e79193a3cff5d6f1c92f22349fd2227d936 # Black
cd758543f17a2253b5a0630327eac0ad6780217a # Trailing whitespace, pyupgrade, prefer builtin constructors
dfd137fc8d3073ff065347401f528c1eaf62c383 # ruff


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: Report a bug
description: Report a bug in pyvex
labels: [bug,needs-triage]
body:
  - type: markdown
    attributes:
      value: |
        Thank you for taking the time to submit this bug report!

        Before submitting this bug report, please check the following, which may resolve your issue:
        * Have you checked that you are running the latest versions of angr and its components? angr is rapidly-evolving!
        * Have you [searched existing issues](https://github.com/angr/pyvex/issues?q=is%3Aopen+is%3Aissue+label%3Abug) to see if this bug has been reported before?
        * Have you checked the [documentation](https://docs.angr.io/)?
        * Have you checked the [FAQ](https://docs.angr.io/introductory-errata/faq)?

        **Important:** If this bug is a security vulnerability, please submit it privately. See our [security policy](https://github.com/angr/angr/blob/master/SECURITY.md) for more details.

        Please note: The angr suite is maintained by a small team. While we cannot guarantee any timeliness for fixes and enhancements, we will do our best. For more real-time help with angr, from us and the community, join our [Slack](https://angr.io/invite/).

  - type: textarea
    attributes:
      label: Description
      description: Brief description of the bug, with any relevant log messages.
    validations:
      required: true

  - type: textarea
    attributes:
      label: Steps to reproduce the bug
      description: |
        If appropriate, include both a **script to reproduce the bug**, and if possible **attach the binary used**.

        **Tip:** You can attach files to the issue by first clicking on the textarea to select it, then dragging & dropping the file onto the textarea.
  - type: textarea
    attributes:
      label: Environment
      description: Many common issues are caused by problems with the local Python environment. Before submitting, double-check that your versions of all modules in the angr suite (angr, cle, pyvex, ...) are up to date and include the output of `python -m angr.misc.bug_report` here.

  - type: textarea
    attributes:
      label: Additional context
      description: Any additional context about the problem.


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Join our Slack community
    url: https://angr.io/invite/
    about: For questions and help with angr, you are invited to join the angr Slack community


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.yml
================================================
name: Request a feature
description: Request a new feature for pyvex
labels: [enhancement,needs-triage]
body:
  - type: markdown
    attributes:
      value: |
        Thank you for taking the time to submit this feature request!

        Before submitting this feature request, please check the following:
        * Have you checked that you are running the latest versions of angr and its components? angr is rapidly-evolving!
        * Have you checked the [documentation](https://docs.angr.io/) to see if this feature exists already?
        * Have you [searched existing issues](https://github.com/angr/pyvex/issues?q=is%3Aissue+label%3Aenhancement+) to see if this feature has been requested before?

        Please note: The angr suite is maintained by a small team. While we cannot guarantee any timeliness for fixes and enhancements, we will do our best. For more real-time help with angr, from us and the community, join our [Slack](https://angr.io/invite/).

  - type: textarea
    attributes:
      label: Description
      description: |
        Brief description of the desired feature. If the feature is intended to solve some problem, please clearly describe the problem, including any relevant binaries, etc.

        **Tip:** You can attach files to the issue by first clicking on the textarea to select it, then dragging & dropping the file onto the textarea.
    validations:
      required: true

  - type: textarea
    attributes:
      label: Alternatives
      description: Possible alternative solutions or features that you have considered.

  - type: textarea
    attributes:
      label: Additional context
      description: Any other context or screenshots about the feature request.


================================================
FILE: .github/ISSUE_TEMPLATE/question.yml
================================================
name: Ask a question
description: Ask a question about pyvex
labels: [question,needs-triage]
body:
  - type: markdown
    attributes:
      value: |
        If you have a question about pyvex, that is not a bug report or a feature request, you can ask it here. For more real-time help with pyvex, from us and the community, join our [Slack](https://angr.io/invite/).

        Before submitting this question, please check the following, which may answer your question:
        * Have you checked the [documentation](https://docs.angr.io/)?
        * Have you checked the [FAQ](https://docs.angr.io/introductory-errata/faq)?
        * Have you checked our library of [examples](https://github.com/angr/angr-doc/tree/master/examples)?
        * Have you [searched existing issues](https://github.com/angr/pyvex/issues?q=is%3Aissue+label%3Aquestion) to see if this question has been answered before?
        * Have you checked that you are running the latest versions of angr and its components. angr is rapidly-evolving!

        Please note: The angr suite is maintained by a small team. While we cannot guarantee any timeliness for fixes and enhancements, we will do our best.

  - type: textarea
    attributes:
      label: Question
      description:
    validations:
      required: true


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches:
      - master
  pull_request:
  workflow_dispatch:

jobs:
  ecosystem:
    uses: angr/ci-settings/.github/workflows/angr-ci.yml@master

  test:
    name: Test
    strategy:
      matrix:
        os: [windows-2022, macos-15-intel, macos-15, ubuntu-24.04]
      fail-fast: false
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
        with:
          submodules: 'recursive'
      - name: Activate msvc
        uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1
        if: startsWith(runner.os, 'windows')
      - name: Setup uv
        uses: astral-sh/setup-uv@445689ea25e0de0a23313031f5fe577c74ae45a1 # v6
      - name: Sync dependencies
        run: uv sync -p 3.10
      - name: Run tests
        run: uv run pytest tests



================================================
FILE: .github/workflows/cifuzz.yml
================================================
name: OSS-Fuzz

on:
  # push:
  #   branches:
  #     - master
  # pull_request:
  workflow_dispatch:

permissions: {}

jobs:
 Fuzzing:
   runs-on: ubuntu-latest
   permissions:
     security-events: write
   steps:
   - name: Build Fuzzers
     id: build
     uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
     with:
       oss-fuzz-project-name: 'pyvex'
       language: python
   - name: Run Fuzzers
     uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
     with:
       oss-fuzz-project-name: 'pyvex'
       language: python
       fuzz-seconds: 600
       output-sarif: true
   - name: Upload Crash
     uses: actions/upload-artifact@v3
     if: failure() && steps.build.outcome == 'success'
     with:
       name: artifacts
       path: ./out/artifacts
   - name: Upload Sarif
     if: always() && steps.build.outcome == 'success'
     uses: github/codeql-action/upload-sarif@v2
     with:
      # Path to SARIF file relative to the root of the repository
      sarif_file: cifuzz-sarif/results.sarif
      checkout_path: cifuzz-sarif


================================================
FILE: .github/workflows/nightly-ci.yml
================================================
name: Nightly CI

on:
  schedule:
  - cron: "0 0 * * *"
  workflow_dispatch:

jobs:
  ci:
    uses: angr/ci-settings/.github/workflows/angr-ci.yml@master
    with:
      nightly: true
    secrets: inherit


================================================
FILE: .gitignore
================================================
build
dist
MANIFEST
pyvex_python
vex_ffi.py
libpyvex.so
*.egg-info
*.eggs
*.pyc
*.swp
*.obj
*.lib
*.dll
*.exp
*.o
*.a
*.dylib
pyvex/lib
pyvex/include
vex-master
vex-master.tar.gz
docs/_build
scikit_build
uv.lock


================================================
FILE: .gitmodules
================================================
[submodule "vex"]
	path = vex
	url = https://github.com/angr/vex.git
	branch = master


================================================
FILE: .pre-commit-config.yaml
================================================
repos:

#
# Fail fast
#

-   repo: https://github.com/abravalheri/validate-pyproject
    rev: v0.25
    hooks:
    - id: validate-pyproject
      fail_fast: true

-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
    # General
    -   id: check-merge-conflict
        fail_fast: true
    -   id: check-case-conflict
        fail_fast: true
    -   id: destroyed-symlinks
        fail_fast: true
    -   id: check-symlinks
        fail_fast: true
    -   id: check-added-large-files
        fail_fast: true
    # Syntax
    -   id: check-toml
        fail_fast: true
    -   id: check-json
        fail_fast: true
    -   id: check-yaml
        fail_fast: true

-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
    -   id: check-ast
        fail_fast: true

#
# Modifiers
#

-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
    -   id: mixed-line-ending
    -   id: trailing-whitespace

-   repo: https://github.com/dannysepler/rm_unneeded_f_str
    rev: v0.2.0
    hooks:
    -   id: rm-unneeded-f-str

-   repo: https://github.com/asottile/pyupgrade
    rev: v3.21.2
    hooks:
    -   id: pyupgrade
        args: [--py310-plus]

-   repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.10
    hooks:
    - id: ruff
      args: [--fix, --exit-non-zero-on-fix]

# Last modifier: Coding Standard
-   repo: https://github.com/psf/black-pre-commit-mirror
    rev: 26.3.1
    hooks:
    -   id: black

#
# Static Checks
#

-   repo: https://github.com/pre-commit/pygrep-hooks
    rev: v1.10.0
    hooks:
    # Python
    -   id: python-use-type-annotations
    -   id: python-no-log-warn
    # Documentation
    -   id: rst-backticks
    -   id: rst-directive-colons
    -   id: rst-inline-touching-normal

-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
    -   id: debug-statements
    -   id: check-builtin-literals
    -   id: check-docstring-first


================================================
FILE: .readthedocs.yml
================================================
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

sphinx:
  configuration: docs/conf.py

submodules:
  include: all

build:
  os: ubuntu-22.04
  tools:
    python: "3.10"
  jobs:
    pre_install:
      - pip install -U pip
      - pip install git+https://github.com/angr/archinfo.git

python:
  install:
    - method: pip
      path: .
      extra_requirements:
        - docs


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.15)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

project(pyvex LANGUAGES C)

# Set the output directory for built libraries
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/pyvex/lib)

# Set the C standard to C99
set(CMAKE_C_STANDARD 99)

# Include directories
include_directories(
    ${CMAKE_SOURCE_DIR}/pyvex/include
    ${CMAKE_SOURCE_DIR}/pyvex_c
    ${CMAKE_SOURCE_DIR}/vex/pub
)

# Source files for the pyvex C library
set(PYVEX_SRC
    pyvex_c/pyvex.c
    pyvex_c/analysis.c
    pyvex_c/logging.c
    pyvex_c/postprocess.c
)

# Source files for the VEX C library
set(VEX_SRC
	vex/priv/ir_defs.c
	vex/priv/ir_match.c
	vex/priv/ir_opt.c
	vex/priv/ir_inject.c
	vex/priv/main_globals.c
	vex/priv/main_util.c
	vex/priv/s390_disasm.c
	vex/priv/host_x86_defs.c
	vex/priv/host_amd64_defs.c
	vex/priv/host_arm_defs.c
	vex/priv/host_arm64_defs.c
	vex/priv/host_ppc_defs.c
	vex/priv/host_riscv64_defs.c
	vex/priv/host_s390_defs.c
	vex/priv/host_mips_defs.c
	vex/priv/host_x86_isel.c
	vex/priv/host_amd64_isel.c
	vex/priv/host_arm_isel.c
	vex/priv/host_arm64_isel.c
	vex/priv/host_ppc_isel.c
	vex/priv/host_riscv64_isel.c
	vex/priv/host_s390_isel.c
	vex/priv/host_mips_isel.c
	vex/priv/host_generic_maddf.c
	vex/priv/host_generic_regs.c
	vex/priv/host_generic_simd64.c
	vex/priv/host_generic_simd128.c
	vex/priv/host_generic_simd256.c
	vex/priv/host_generic_reg_alloc2.c
	vex/priv/host_generic_reg_alloc3.c
	vex/priv/guest_generic_x87.c
	vex/priv/guest_generic_bb_to_IR.c
	vex/priv/guest_x86_helpers.c
	vex/priv/guest_amd64_helpers.c
	vex/priv/guest_arm_helpers.c
	vex/priv/guest_arm64_helpers.c
	vex/priv/guest_ppc_helpers.c
	vex/priv/guest_riscv64_helpers.c
	vex/priv/guest_s390_helpers.c
	vex/priv/guest_mips_helpers.c
	vex/priv/guest_x86_toIR.c
	vex/priv/guest_amd64_toIR.c
	vex/priv/guest_arm_toIR.c
	vex/priv/guest_arm64_toIR.c
	vex/priv/guest_ppc_toIR.c
	vex/priv/guest_riscv64_toIR.c
	vex/priv/guest_s390_toIR.c
	vex/priv/guest_mips_toIR.c
    vex/priv/multiarch_main_main.c
)

# Build the VEX static library
add_library(vex STATIC ${VEX_SRC})
target_compile_definitions(vex PRIVATE PYVEX)
target_include_directories(vex PUBLIC ${CMAKE_SOURCE_DIR}/vex/pub)

# Build the shared library
add_library(pyvex SHARED ${PYVEX_SRC})
set_target_properties(pyvex PROPERTIES OUTPUT_NAME "pyvex")

# Handle .def file for Windows builds
if (WIN32)
    set_target_properties(pyvex PROPERTIES LINK_FLAGS "/DEF:${CMAKE_SOURCE_DIR}/pyvex_c/pyvex.def")
endif()

target_include_directories(pyvex PRIVATE pyvex_c)

target_link_libraries(pyvex PRIVATE vex)

# Install the built library to the Python package
# It is installed twice to handle both editable and non-editable installs
install(TARGETS pyvex DESTINATION ${CMAKE_SOURCE_DIR}/pyvex/lib)
install(TARGETS pyvex DESTINATION pyvex/lib)

# --- BEGIN: Generate pub/libvex_guest_offsets.h ---
add_executable(genoffsets vex/auxprogs/genoffsets.c)
set_target_properties(genoffsets PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/vex/auxprogs)

add_custom_command(
    OUTPUT ${CMAKE_SOURCE_DIR}/vex/pub/libvex_guest_offsets.h
    COMMAND $<TARGET_FILE:genoffsets> > ${CMAKE_SOURCE_DIR}/vex/pub/libvex_guest_offsets.h
    DEPENDS genoffsets
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    COMMENT "Generating pub/libvex_guest_offsets.h"
)

add_custom_target(generate_offsets_header
    DEPENDS ${CMAKE_SOURCE_DIR}/vex/pub/libvex_guest_offsets.h
)
install(
    FILES ${CMAKE_SOURCE_DIR}/vex/pub/libvex_guest_offsets.h
    DESTINATION pyvex/include
)

add_dependencies(vex generate_offsets_header)
# --- END: Generate pub/libvex_guest_offsets.h ---

# --- BEGIN: Generate pyvex/vex_ffi.py ---
add_custom_command(
    OUTPUT ${CMAKE_SOURCE_DIR}/pyvex/vex_ffi.py
    COMMAND ${CMAKE_COMMAND} -E env
        ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/make_ffi.py ${CMAKE_SOURCE_DIR}/vex/pub
    DEPENDS ${CMAKE_SOURCE_DIR}/vex/pub/libvex_guest_offsets.h
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    COMMENT "Generating pyvex/vex_ffi.py using make_ffi.py"
)

add_custom_target(generate_vex_ffi_py
    DEPENDS ${CMAKE_SOURCE_DIR}/pyvex/vex_ffi.py
)
install(
    FILES ${CMAKE_SOURCE_DIR}/pyvex/vex_ffi.py
    DESTINATION pyvex
)
add_dependencies(pyvex generate_vex_ffi_py)
# --- END: Generate pyvex/vex_ffi.py ---

# --- BEGIN: Copy headers to pyvex/include ---
add_custom_command(
    OUTPUT ${CMAKE_SOURCE_DIR}/pyvex/include/pub
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/vex/pub ${CMAKE_SOURCE_DIR}/pyvex/include/
    DEPENDS ${CMAKE_SOURCE_DIR}/vex/pub
    COMMENT "Copying vex/pub to pyvex/include/"
)
add_custom_command(
    OUTPUT ${CMAKE_SOURCE_DIR}/pyvex/include/pyvex.h
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/pyvex_c/pyvex.h ${CMAKE_SOURCE_DIR}/pyvex/include/pyvex.h
    DEPENDS ${CMAKE_SOURCE_DIR}/pyvex_c/pyvex.h
    COMMENT "Copying pyvex_c/pyvex.h to pyvex/include/"
)
add_custom_target(copy_headers ALL
    DEPENDS ${CMAKE_SOURCE_DIR}/pyvex/include/pub ${CMAKE_SOURCE_DIR}/pyvex/include/pyvex.h
)
add_dependencies(pyvex copy_headers)
add_dependencies(copy_headers generate_offsets_header)
# --- END: Copy headers to pyvex/include ---


================================================
FILE: LICENSE
================================================
Copyright (c) 2015, The Regents of the University of California
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.



================================================
FILE: MANIFEST.in
================================================
include LICENSE
include README.md
include make_ffi.py
recursive-include pyvex_c *.c *.h *.def Makefile Makefile-msvc LICENSE
recursive-include vex *


================================================
FILE: README.md
================================================
# PyVEX
[![Latest Release](https://img.shields.io/pypi/v/pyvex.svg)](https://pypi.python.org/pypi/pyvex/)
[![Python Version](https://img.shields.io/pypi/pyversions/pyvex)](https://pypi.python.org/pypi/pyvex/)
[![PyPI Statistics](https://img.shields.io/pypi/dm/pyvex.svg)](https://pypistats.org/packages/pyvex)
[![License](https://img.shields.io/github/license/angr/pyvex.svg)](https://github.com/angr/pyvex/blob/master/LICENSE)

PyVEX is Python bindings for the VEX IR.

## Project Links
Project repository: https://github.com/angr/pyvex

Documentation: https://api.angr.io/projects/pyvex/en/latest/

## Installing PyVEX

PyVEX can be pip-installed:

```bash
pip install pyvex
```

## Using PyVEX

```python
import pyvex
import archinfo

# translate an AMD64 basic block (of nops) at 0x400400 into VEX
irsb = pyvex.lift(b"\x90\x90\x90\x90\x90", 0x400400, archinfo.ArchAMD64())

# pretty-print the basic block
irsb.pp()

# this is the IR Expression of the jump target of the unconditional exit at the end of the basic block
print(irsb.next)

# this is the type of the unconditional exit (i.e., a call, ret, syscall, etc)
print(irsb.jumpkind)

# you can also pretty-print it
irsb.next.pp()

# iterate through each statement and print all the statements
for stmt in irsb.statements:
    stmt.pp()

# pretty-print the IR expression representing the data, and the *type* of that IR expression written by every store statement
import pyvex
for stmt in irsb.statements:
    if isinstance(stmt, pyvex.IRStmt.Store):
        print("Data:", end="")
        stmt.data.pp()
        print("")

        print("Type:", end="")
        print(stmt.data.result_type)
        print("")

# pretty-print the condition and jump target of every conditional exit from the basic block
for stmt in irsb.statements:
    if isinstance(stmt, pyvex.IRStmt.Exit):
        print("Condition:", end="")
        stmt.guard.pp()
        print("")

        print("Target:", end="")
        stmt.dst.pp()
        print("")

# these are the types of every temp in the IRSB
print(irsb.tyenv.types)

# here is one way to get the type of temp 0
print(irsb.tyenv.types[0])
```

Keep in mind that this is a *syntactic* representation of a basic block. That is, it'll tell you what the block means, but you don't have any context to say, for example, what *actual* data is written by a store instruction.

## VEX Intermediate Representation

To deal with widely diverse architectures, it is useful to carry out analyses on an intermediate representation.
An IR abstracts away several architecture differences when dealing with different architectures, allowing a single analysis to be run on all of them:

- **Register names.** The quantity and names of registers differ between architectures, but modern CPU designs hold to a common theme: each CPU contains several general purpose registers, a register to hold the stack pointer, a set of registers to store condition flags, and so forth. The IR provides a consistent, abstracted interface to registers on different platforms. Specifically, VEX models the registers as a separate memory space, with integer offsets (i.e., AMD64's `rax` is stored starting at address 16 in this memory space).
- **Memory access.** Different architectures access memory in different ways. For example, ARM can access memory in both little-endian and big-endian modes. The IR must abstract away these differences.
- **Memory segmentation.** Some architectures, such as x86, support memory segmentation through the use of special segment registers. The IR understands such memory access mechanisms.
- **Instruction side-effects.** Most instructions have side-effects. For example, most operations in Thumb mode on ARM update the condition flags, and stack push/pop instructions update the stack pointer. Tracking these side-effects in an *ad hoc* manner in the analysis would be crazy, so the IR makes these effects explicit.

There are lots of choices for an IR. We use VEX, since the uplifting of binary code into VEX is quite well supported.
VEX is an architecture-agnostic, side-effects-free representation of a number of target machine languages.
It abstracts machine code into a representation designed to make program analysis easier.
This representation has five main classes of objects:

- **Expressions.** IR Expressions represent a calculated or constant value. This includes memory loads, register reads, and results of arithmetic operations.
- **Operations.** IR Operations describe a *modification* of IR Expressions. This includes integer arithmetic, floating-point arithmetic, bit operations, and so forth. An IR Operation applied to IR Expressions yields an IR Expression as a result.
- **Temporary variables.** VEX uses temporary variables as internal registers: IR Expressions are stored in temporary variables between use. The content of a temporary variable can be retrieved using an IR Expression. These temporaries are numbered, starting at `t0`. These temporaries are strongly typed (i.e., "64-bit integer" or "32-bit float").
- **Statements.** IR Statements model changes in the state of the target machine, such as the effect of memory stores and register writes. IR Statements use IR Expressions for values they may need. For example, a memory store *IR Statement* uses an *IR Expression* for the target address of the write, and another *IR Expression* for the content.
- **Blocks.** An IR Block is a collection of IR Statements, representing an extended basic block (termed "IR Super Block" or "IRSB") in the target architecture. A block can have several exits. For conditional exits from the middle of a basic block, a special *Exit* IR Statement is used. An IR Expression is used to represent the target of the unconditional exit at the end of the block.

VEX IR is actually quite well documented in the `libvex_ir.h` file (https://github.com/angr/vex/blob/dev/pub/libvex_ir.h) in the VEX repository. For the lazy, we'll detail some parts of VEX that you'll likely interact with fairly frequently. To begin with, here are some IR Expressions:

| IR Expression | Evaluated Value | VEX Output Example |
| ------------- | --------------- | ------- |
| Constant | A constant value. | 0x4:I32 |
| Read Temp | The value stored in a VEX temporary variable. | RdTmp(t10) |
| Get Register | The value stored in a register. | GET:I32(16) |
| Load Memory | The value stored at a memory address, with the address specified by another IR Expression. | LDle:I32 / LDbe:I64 |
| Operation | A result of a specified IR Operation, applied to specified IR Expression arguments. | Add32 |
| If-Then-Else | If a given IR Expression evaluates to 0, return one IR Expression. Otherwise, return another. | ITE |
| Helper Function | VEX uses C helper functions for certain operations, such as computing the conditional flags registers of certain architectures. These functions return IR Expressions. | function\_name() |

These expressions are then, in turn, used in IR Statements. Here are some common ones:

| IR Statement | Meaning | VEX Output Example |
| ------------ | ------- | ------------------ |
Write Temp | Set a VEX temporary variable to the value of the given IR Expression. | WrTmp(t1) = (IR Expression) |
Put Register | Update a register with the value of the given IR Expression. | PUT(16) = (IR Expression) |
Store Memory | Update a location in memory, given as an IR Expression, with a value, also given as an IR Expression. | STle(0x1000) = (IR Expression) |
Exit | A conditional exit from a basic block, with the jump target specified by an IR Expression. The condition is specified by an IR Expression. | if (condition) goto (Boring) 0x4000A00:I32 |

An example of an IR translation, on ARM, is produced below. In the example, the subtraction operation is translated into a single IR block comprising 5 IR Statements, each of which contains at least one IR Expression (although, in real life, an IR block would typically consist of more than one instruction). Register names are translated into numerical indices given to the *GET* Expression and *PUT* Statement.
The astute reader will observe that the actual subtraction is modeled by the first 4 IR Statements of the block, and the incrementing of the program counter to point to the next instruction (which, in this case, is located at `0x59FC8`) is modeled by the last statement.

The following ARM instruction:

    subs R2, R2, #8

Becomes this VEX IR:

    t0 = GET:I32(16)
    t1 = 0x8:I32
    t3 = Sub32(t0,t1)
    PUT(16) = t3
    PUT(68) = 0x59FC8:I32

Cool stuff!

## Citing PyVEX

If you use PyVEX in an academic work, please cite the paper for which it was developed:

```bibtex
@article{shoshitaishvili2015firmalice,
  title={Firmalice - Automatic Detection of Authentication Bypass Vulnerabilities in Binary Firmware},
  author={Shoshitaishvili, Yan and Wang, Ruoyu and Hauser, Christophe and Kruegel, Christopher and Vigna, Giovanni},
  booktitle={NDSS},
  year={2015}
}
```


================================================
FILE: docs/Makefile
================================================
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build

# Put it first so that "make" without argument is like "make help".
help:
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)


================================================
FILE: docs/api.rst
================================================
:mod:`pyvex` --- Binary Translator
==================================

.. automodule:: pyvex
.. automodule:: pyvex.native


Translation Interface
---------------------

.. automodule:: pyvex.block


IR Components
-------------

.. automodule:: pyvex.stmt
.. automodule:: pyvex.expr
.. automodule:: pyvex.const
.. automodule:: pyvex.enums

Lifting System
--------------

.. automodule:: pyvex.data_ref
.. automodule:: pyvex.lifting
.. automodule:: pyvex.lifting.lift_function
.. automodule:: pyvex.lifting.libvex
.. automodule:: pyvex.lifting.lifter
.. automodule:: pyvex.lifting.post_processor
.. automodule:: pyvex.lifting.util.irsb_postprocess
.. automodule:: pyvex.lifting.util
.. automodule:: pyvex.lifting.util.syntax_wrapper
.. automodule:: pyvex.lifting.util.vex_helper
.. automodule:: pyvex.lifting.util.lifter_helper
.. automodule:: pyvex.lifting.util.instr_helper

Builtin IR Processors
---------------------

.. automodule:: pyvex.lifting.zerodivision

Errors
------

.. automodule:: pyvex.errors

Utilities
---------

.. automodule:: pyvex.utils


================================================
FILE: docs/conf.py
================================================
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

import datetime

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = "pyvex"
project_copyright = f"{datetime.datetime.now().year}, The angr Project contributors"
author = "The angr Project"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.autosummary",
    "sphinx.ext.coverage",
    "sphinx.ext.napoleon",
    "sphinx.ext.todo",
    "sphinx.ext.viewcode",
    "sphinx_autodoc_typehints",
    "myst_parser",
]

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]

# -- Options for autodoc -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#configuration
autoclass_content = "class"
autodoc_default_options = {
    "members": True,
    "member-order": "bysource",
    "show-inheritance": True,
    "special-members": "__init__",
    "undoc-members": True,
}
autodoc_inherit_docstrings = True
autodoc_typehints = "both"

# -- Options for coverage ----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/coverage.html
coverage_write_headline = False


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = "furo"
html_static_path = ["_static"]


================================================
FILE: docs/index.rst
================================================
Welcome to pyVEX's documentation!
=================================


.. toctree::
   :maxdepth: 2
   :caption: Contents:

   Quickstart <quickstart>
   API <api>



Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`


================================================
FILE: docs/make.bat
================================================
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
	set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
	echo.
	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
	echo.installed, then set the SPHINXBUILD environment variable to point
	echo.to the full path of the 'sphinx-build' executable. Alternatively you
	echo.may add the Sphinx directory to PATH.
	echo.
	echo.If you don't have Sphinx installed, grab it from
	echo.https://www.sphinx-doc.org/
	exit /b 1
)

if "%1" == "" goto help

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd


================================================
FILE: docs/quickstart.rst
================================================
.. include:: ../README.md
   :parser: myst_parser.sphinx_


================================================
FILE: fuzzing/build.sh
================================================
#!/bin/bash -eu
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################

# Since pyvex requires a specific developer build of archinfo, install it from source
cd "$SRC"/archinfo
python3 -m pip install .

cd "$SRC"/pyvex
python3 -m pip install .[testing]

# Generate a simple binary for the corpus
echo -ne "start:\n\txor %edi, %edi\nmov \$60, %eax\nsyscall" > /tmp/corpus.s
clang -Os -s /tmp/corpus.s -nostdlib -nostartfiles -m32 -o corpus
zip -r "$OUT"/irsb_fuzzer_seed_corpus.zip corpus

# Build fuzzers in $OUT
# --collect-submodules=bitstring ensures all bitstring submodules are bundled by PyInstaller
for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
  compile_python_fuzzer "$fuzzer" \
    --add-binary="pyvex/lib/libpyvex.so:pyvex/lib" \
    --collect-submodules=bitstring
done


================================================
FILE: fuzzing/enhanced_fdp.py
================================================
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
"""
Defines the EnhancedFuzzedDataProvider
"""

from atheris import FuzzedDataProvider


class EnhancedFuzzedDataProvider(FuzzedDataProvider):
    """
    Extends the functionality of FuzzedDataProvider
    """

    def _consume_random_count(self) -> int:
        """
        :return: A count of bytes that is strictly in range 0<=n<=remaining_bytes
        """
        return self.ConsumeIntInRange(0, self.remaining_bytes())

    def ConsumeRandomBytes(self) -> bytes:
        """
        Consume a 'random' count of the remaining bytes
        :return: 0<=n<=remaining_bytes bytes
        """
        return self.ConsumeBytes(self._consume_random_count())

    def ConsumeRemainingBytes(self) -> bytes:
        """
        :return: The remaining buffer
        """
        return self.ConsumeBytes(self.remaining_bytes())

    def ConsumeRandomString(self) -> str:
        """
        Consume a 'random' length string, excluding surrogates
        :return: The string
        """
        return self.ConsumeUnicodeNoSurrogates(self._consume_random_count())

    def ConsumeRemainingString(self) -> str:
        """
        :return: The remaining buffer, as a string without surrogates
        """
        return self.ConsumeUnicodeNoSurrogates(self.remaining_bytes())

    def PickValueInEnum(self, enum):
        return self.PickValueInList([e.value for e in enum])


================================================
FILE: fuzzing/irsb_fuzzer.py
================================================
#!/usr/bin/python3
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
import re
import sys
from contextlib import contextmanager
from enum import IntEnum
from io import StringIO

import atheris

with atheris.instrument_imports(include=["pyvex"]):
    import pyvex

# Additional imports
from enhanced_fdp import EnhancedFuzzedDataProvider

register_error_msg = re.compile("Register .*? does not exist!")


@contextmanager
def nostdout():
    saved_stdout = sys.stdout
    saved_stderr = sys.stderr
    sys.stdout = StringIO()
    sys.stderr = StringIO()
    yield
    sys.stdout = saved_stdout
    sys.stderr = saved_stderr


# Save all available architectures off
available_archs = [
    pyvex.ARCH_X86,
    pyvex.ARCH_AMD64,
    pyvex.ARCH_ARM_LE,
    pyvex.ARCH_ARM_BE,
    pyvex.ARCH_ARM64_LE,
    pyvex.ARCH_ARM64_BE,
    pyvex.ARCH_PPC32,
    pyvex.ARCH_PPC64_BE,
    pyvex.ARCH_PPC64_LE,
    pyvex.ARCH_S390X,
    pyvex.ARCH_MIPS32_BE,
    pyvex.ARCH_MIPS32_LE,
    pyvex.ARCH_MIPS64_BE,
    pyvex.ARCH_MIPS64_LE,
]


class SupportedOptLevels(IntEnum):
    """
    Enumerates the supported optimization levels within pyvex, as derived from the documentation
    """

    StrictUnopt = -1
    Unopt = 0
    Opt = 1
    StrictOpt = 2


def consume_random_arch(fdp: atheris.FuzzedDataProvider) -> pyvex.arches.PyvexArch:
    return fdp.PickValueInList(available_archs)


def TestOneInput(data: bytes):
    fdp = EnhancedFuzzedDataProvider(data)

    arch = consume_random_arch(fdp)

    try:
        with nostdout():
            data = fdp.ConsumeRandomBytes()
            max_bytes = fdp.ConsumeIntInRange(0, len(data))
            irsb = pyvex.lift(
                data,
                fdp.ConsumeInt(arch.bits),
                arch,
                max_bytes=fdp.ConsumeIntInRange(0, len(data)),
                max_inst=fdp.ConsumeInt(16),
                bytes_offset=fdp.ConsumeIntInRange(0, max_bytes),
                opt_level=fdp.PickValueInEnum(SupportedOptLevels),
            )
            irsb.pp()
        return 0
    except pyvex.PyVEXError:
        return -1
    except ValueError as e:
        if re.match(register_error_msg, str(e)):
            return -1
        raise e
    except OverflowError:
        return -1


def main():
    atheris.Setup(sys.argv, TestOneInput)
    atheris.Fuzz()


if __name__ == "__main__":
    main()


================================================
FILE: make_ffi.py
================================================
import logging
import os
import platform
import re
import subprocess
import sys

import cffi

log = logging.getLogger("cffier")
log.setLevel(logging.DEBUG)


def find_good_scan(questionable):
    known_good = []

    end_line = len(questionable)

    while len(questionable):
        ffi = cffi.FFI()
        log.debug("scan - trying %d good and %d questionable", len(known_good), len(questionable))

        candidate = known_good + questionable[:end_line]
        failed_line = -1

        try:
            ffi.cdef("\n".join(candidate))

            known_good = candidate
            questionable = questionable[end_line:]
            end_line = len(questionable)
        except AssertionError:
            questionable = questionable[1:]
            end_line = len(questionable)
        except cffi.CDefError as e:
            if "<cdef source string>" in str(e):
                failed_line = int(str(e).split("\n")[-1].split(":")[1]) - 1
            elif str(e).count(":") >= 2:
                failed_line = int(str(e).split("\n")[1].split(":")[1])
                failed_line_description = str(e).split("\n")[0]
                idx1 = failed_line_description.index('"')
                idx2 = failed_line_description.rindex('"')
                failed_reason = failed_line_description[idx1 + 1 : idx2]

                for i in range(failed_line, -1, -1):
                    if failed_reason in candidate[i]:
                        failed_line = i
            elif "unrecognized construct" in str(e):
                failed_line = int(str(e).split()[1][:-1]) - 1
            elif "end of input" in str(e):
                end_line -= 1
            else:
                raise Exception("Unknown error")
        except cffi.FFIError as e:
            if str(e).count(":") >= 2:
                failed_line = int(str(e).split("\n")[0].split(":")[1]) - 1
            else:
                raise Exception("Unknown error")

        if failed_line != -1:
            end_line = failed_line - len(known_good)

        if end_line == 0:
            questionable = questionable[1:]
            end_line = len(questionable)
    return known_good


def doit(vex_path):
    cpplist = ["cl", "cpp"]
    cpp = os.getenv("CPP")
    if cpp:
        cpplist.insert(0, cpp)
    if platform.system() == "Darwin":
        cpplist.insert(0, "clang")

    errs = []
    for cpp in cpplist:
        cmd = [cpp, "-I" + vex_path, os.path.join("pyvex_c", "pyvex.h")]
        if cpp in ("cl", "clang", "gcc", "cc", "clang++", "g++"):
            cmd.append("-E")
        try:
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            header, stderr = p.communicate()
            try:
                header = header.decode("utf-8")
                stderr = stderr.decode("utf-8")
            except UnicodeDecodeError:
                # They don't have to be unicode on Windows
                pass

            if not header.strip() or p.returncode != 0:
                errs.append((" ".join(cmd), p.returncode, stderr))
                continue
            else:
                break
        except OSError:
            errs.append((" ".join(cmd), -1, "does not exist"))
            continue
    else:
        log.warning("failed commands:\n" + "\n".join("{} ({}) -- {}".format(*e) for e in errs))
        raise Exception(
            "Couldn't process pyvex headers."
            + 'Please set CPP environmental variable to local path of "cpp".'
            + 'Note that "cpp" and "g++" are different.'
        )
    # header = vex_pp + pyvex_pp

    linesep = "\r\n" if "\r\n" in header else "\n"
    ffi_text = linesep.join(
        line
        for line in header.split(linesep)
        if "#" not in line and line.strip() != "" and "jmp_buf" not in line and not ("=" in line and ";" in line)
    )
    ffi_text = re.sub(r"\{\s*\} NoOp;", "{ int DONOTUSE; } NoOp;", ffi_text)
    ffi_text = re.sub(r"__attribute__\s*\(.*\)", "", ffi_text)
    ffi_text = re.sub(r"__declspec\s*\([^\)]*\)", "", ffi_text)
    ffi_text = ffi_text.replace("__const", "const")
    ffi_text = ffi_text.replace("__inline", "")
    ffi_text = ffi_text.replace("__w64", "")
    ffi_text = ffi_text.replace("__cdecl", "")
    ffi_text = ffi_text.replace("__int64", "long")
    ffi_lines = ffi_text.split(linesep)

    good = find_good_scan(ffi_lines)
    good += ["extern VexControl vex_control;"]

    with open("pyvex/vex_ffi.py", "w") as fp:
        fp.write('ffi_str = """' + "\n".join(good) + '"""\n')
        fp.write("guest_offsets = " + repr(get_guest_offsets(vex_path)) + "\n")


def get_guest_offsets(vex_path):
    fname = os.path.join(vex_path, "libvex_guest_offsets.h")
    out = {}
    with open(fname) as fp:
        for line in fp:
            if line.startswith("#define"):
                _, names, val = line.split()
                val = int(val, 0)
                assert names.startswith("OFFSET_")
                _, arch, reg = names.split("_", 2)
                out[(arch, reg.lower())] = val
    return out


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    doit(sys.argv[1])


================================================
FILE: pyproject.toml
================================================
[build-system]
requires = ["scikit-build-core >= 0.11.4, < 0.12.0", "cffi >= 1.0.3;implementation_name == 'cpython'"]
build-backend = "scikit_build_core.build"

[project]
name = "pyvex"
description = "A Python interface to libVEX and VEX IR"
license = "BSD-2-Clause AND GPL-2.0-only"
license-files = [
  "LICENSE",
  "pyvex_c/LICENSE",
  "vex/LICENSE.README",
  "vex/LICENSE.GPL",
]
classifiers = [
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
]
requires-python = ">=3.10"
dependencies = [
    "bitstring",
    "cffi>=1.0.3;implementation_name == 'cpython'",
]
dynamic = ["version"]

[project.readme]
file = "README.md"
content-type = "text/markdown"

[project.urls]
Homepage = "https://api.angr.io/projects/pyvex/en/latest/"
Repository = "https://github.com/angr/pyvex"

[project.optional-dependencies]
docs = [
    "furo",
    "myst-parser",
    "sphinx",
    "sphinx-autodoc-typehints",
]
fuzzing = [
    "atheris>=2.3.0",
]
testing = [
    "pytest",
    "pytest-xdist",
]

[dependency-groups]
dev = [
    "pytest>=8.4.1",
]

[tool.scikit-build]
build-dir = "scikit_build"

[tool.scikit-build.sdist]
include = [
  "pyvex/py.typed",
  "pyvex/include/*",
]
exclude = [
  "tests*"
]

[tool.scikit-build.metadata.version]
provider = "scikit_build_core.metadata.regex"
input = "pyvex/__init__.py"

[tool.black]
line-length = 120
target-version = ['py310']
force-exclude = '''
/(
  vex
)/
'''

[tool.ruff]
line-length = 120

[tool.ruff.lint]
select = [
  "E",
  "F",
  "I",
  "TID",
]


================================================
FILE: pyvex/__init__.py
================================================
"""
PyVEX provides an interface that translates binary code into the VEX intermediate representation (IR).
For an introduction to VEX, take a look here: https://docs.angr.io/advanced-topics/ir
"""

__version__ = "9.2.212.dev0"

from . import const, expr, stmt
from .arches import (
    ARCH_AMD64,
    ARCH_ARM64_BE,
    ARCH_ARM64_LE,
    ARCH_ARM_BE,
    ARCH_ARM_BE_LE,
    ARCH_ARM_LE,
    ARCH_MIPS32_BE,
    ARCH_MIPS32_LE,
    ARCH_MIPS64_BE,
    ARCH_MIPS64_LE,
    ARCH_PPC32,
    ARCH_PPC64_BE,
    ARCH_PPC64_LE,
    ARCH_RISCV64_LE,
    ARCH_S390X,
    ARCH_X86,
)
from .block import IRSB, IRTypeEnv
from .const import get_type_size, get_type_spec_size, tag_to_const_class
from .enums import (
    IRCallee,
    IRRegArray,
    VEXObject,
    default_vex_archinfo,
    get_enum_from_int,
    get_int_from_enum,
    irop_enums_to_ints,
    vex_endness_from_string,
)
from .errors import PyVEXError
from .expr import get_op_retty
from .lifting import lift, lifters
from .native import ffi, pvc

# aliases....
IRStmt = stmt
IRExpr = expr
IRConst = const


__all__ = [
    "const",
    "expr",
    "stmt",
    "IRSB",
    "IRTypeEnv",
    "get_type_size",
    "get_type_spec_size",
    "irop_enums_to_ints",
    "tag_to_const_class",
    "IRCallee",
    "IRRegArray",
    "VEXObject",
    "default_vex_archinfo",
    "get_enum_from_int",
    "get_int_from_enum",
    "vex_endness_from_string",
    "PyVEXError",
    "get_op_retty",
    "lift",
    "lifters",
    "ffi",
    "pvc",
    "IRStmt",
    "IRExpr",
    "IRConst",
    "ARCH_X86",
    "ARCH_AMD64",
    "ARCH_ARM_BE",
    "ARCH_ARM_BE_LE",
    "ARCH_ARM_LE",
    "ARCH_ARM64_LE",
    "ARCH_ARM64_BE",
    "ARCH_PPC32",
    "ARCH_PPC64_BE",
    "ARCH_PPC64_LE",
    "ARCH_S390X",
    "ARCH_MIPS32_BE",
    "ARCH_MIPS32_LE",
    "ARCH_MIPS64_BE",
    "ARCH_MIPS64_LE",
    "ARCH_RISCV64_LE",
]


================================================
FILE: pyvex/_register_info.py
================================================
REGISTER_OFFSETS = {
    ("x86", "eax"): 8,
    ("x86", "ax"): 8,
    ("x86", "al"): 8,
    ("x86", "ah"): 9,
    ("x86", "ecx"): 12,
    ("x86", "cx"): 12,
    ("x86", "cl"): 12,
    ("x86", "ch"): 13,
    ("x86", "edx"): 16,
    ("x86", "dx"): 16,
    ("x86", "dl"): 16,
    ("x86", "dh"): 17,
    ("x86", "ebx"): 20,
    ("x86", "bx"): 20,
    ("x86", "bl"): 20,
    ("x86", "bh"): 21,
    ("x86", "esp"): 24,
    ("x86", "sp"): 24,
    ("x86", "ebp"): 28,
    ("x86", "bp"): 28,
    ("x86", "esi"): 32,
    ("x86", "si"): 32,
    ("x86", "sil"): 32,
    ("x86", "sih"): 33,
    ("x86", "edi"): 36,
    ("x86", "di"): 36,
    ("x86", "dil"): 36,
    ("x86", "dih"): 37,
    ("x86", "cc_op"): 40,
    ("x86", "cc_dep1"): 44,
    ("x86", "cc_dep2"): 48,
    ("x86", "cc_ndep"): 52,
    ("x86", "d"): 56,
    ("x86", "dflag"): 56,
    ("x86", "id"): 60,
    ("x86", "idflag"): 60,
    ("x86", "ac"): 64,
    ("x86", "acflag"): 64,
    ("x86", "eip"): 68,
    ("x86", "ip"): 68,
    ("x86", "pc"): 68,
    ("x86", "fpreg"): 72,
    ("x86", "fpu_regs"): 72,
    ("x86", "mm0"): 72,
    ("x86", "mm1"): 80,
    ("x86", "mm2"): 88,
    ("x86", "mm3"): 96,
    ("x86", "mm4"): 104,
    ("x86", "mm5"): 112,
    ("x86", "mm6"): 120,
    ("x86", "mm7"): 128,
    ("x86", "fptag"): 136,
    ("x86", "fpu_tags"): 136,
    ("x86", "fpround"): 144,
    ("x86", "fc3210"): 148,
    ("x86", "ftop"): 152,
    ("x86", "sseround"): 156,
    ("x86", "xmm0"): 160,
    ("x86", "xmm1"): 176,
    ("x86", "xmm2"): 192,
    ("x86", "xmm3"): 208,
    ("x86", "xmm4"): 224,
    ("x86", "xmm5"): 240,
    ("x86", "xmm6"): 256,
    ("x86", "xmm7"): 272,
    ("x86", "cs"): 288,
    ("x86", "ds"): 290,
    ("x86", "es"): 292,
    ("x86", "fs"): 294,
    ("x86", "gs"): 296,
    ("x86", "ss"): 298,
    ("x86", "ldt"): 304,
    ("x86", "gdt"): 312,
    ("x86", "emnote"): 320,
    ("x86", "cmstart"): 324,
    ("x86", "cmlen"): 328,
    ("x86", "nraddr"): 332,
    ("x86", "sc_class"): 336,
    ("x86", "ip_at_syscall"): 340,
    ("amd64", "rax"): 16,
    ("amd64", "eax"): 16,
    ("amd64", "ax"): 16,
    ("amd64", "al"): 16,
    ("amd64", "ah"): 17,
    ("amd64", "rcx"): 24,
    ("amd64", "ecx"): 24,
    ("amd64", "cx"): 24,
    ("amd64", "cl"): 24,
    ("amd64", "ch"): 25,
    ("amd64", "rdx"): 32,
    ("amd64", "edx"): 32,
    ("amd64", "dx"): 32,
    ("amd64", "dl"): 32,
    ("amd64", "dh"): 33,
    ("amd64", "rbx"): 40,
    ("amd64", "ebx"): 40,
    ("amd64", "bx"): 40,
    ("amd64", "bl"): 40,
    ("amd64", "bh"): 41,
    ("amd64", "rsp"): 48,
    ("amd64", "sp"): 48,
    ("amd64", "esp"): 48,
    ("amd64", "rbp"): 56,
    ("amd64", "bp"): 56,
    ("amd64", "ebp"): 56,
    ("amd64", "_bp"): 56,
    ("amd64", "bpl"): 56,
    ("amd64", "bph"): 57,
    ("amd64", "rsi"): 64,
    ("amd64", "esi"): 64,
    ("amd64", "si"): 64,
    ("amd64", "sil"): 64,
    ("amd64", "sih"): 65,
    ("amd64", "rdi"): 72,
    ("amd64", "edi"): 72,
    ("amd64", "di"): 72,
    ("amd64", "dil"): 72,
    ("amd64", "dih"): 73,
    ("amd64", "r8"): 80,
    ("amd64", "r8d"): 80,
    ("amd64", "r8w"): 80,
    ("amd64", "r8b"): 80,
    ("amd64", "r9"): 88,
    ("amd64", "r9d"): 88,
    ("amd64", "r9w"): 88,
    ("amd64", "r9b"): 88,
    ("amd64", "r10"): 96,
    ("amd64", "r10d"): 96,
    ("amd64", "r10w"): 96,
    ("amd64", "r10b"): 96,
    ("amd64", "r11"): 104,
    ("amd64", "r11d"): 104,
    ("amd64", "r11w"): 104,
    ("amd64", "r11b"): 104,
    ("amd64", "r12"): 112,
    ("amd64", "r12d"): 112,
    ("amd64", "r12w"): 112,
    ("amd64", "r12b"): 112,
    ("amd64", "r13"): 120,
    ("amd64", "r13d"): 120,
    ("amd64", "r13w"): 120,
    ("amd64", "r13b"): 120,
    ("amd64", "r14"): 128,
    ("amd64", "r14d"): 128,
    ("amd64", "r14w"): 128,
    ("amd64", "r14b"): 128,
    ("amd64", "r15"): 136,
    ("amd64", "r15d"): 136,
    ("amd64", "r15w"): 136,
    ("amd64", "r15b"): 136,
    ("amd64", "cc_op"): 144,
    ("amd64", "cc_dep1"): 152,
    ("amd64", "cc_dep2"): 160,
    ("amd64", "cc_ndep"): 168,
    ("amd64", "d"): 176,
    ("amd64", "dflag"): 176,
    ("amd64", "rip"): 184,
    ("amd64", "ip"): 184,
    ("amd64", "pc"): 184,
    ("amd64", "ac"): 192,
    ("amd64", "acflag"): 192,
    ("amd64", "id"): 200,
    ("amd64", "idflag"): 200,
    ("amd64", "fs"): 208,
    ("amd64", "fs_const"): 208,
    ("amd64", "sseround"): 216,
    ("amd64", "cr0"): 768,
    ("amd64", "cr2"): 784,
    ("amd64", "cr3"): 792,
    ("amd64", "cr4"): 800,
    ("amd64", "cr8"): 832,
    ("amd64", "ymm0"): 224,
    ("amd64", "xmm0"): 224,
    ("amd64", "xmm0lq"): 224,
    ("amd64", "xmm0hq"): 232,
    ("amd64", "ymm0hx"): 240,
    ("amd64", "ymm1"): 256,
    ("amd64", "xmm1"): 256,
    ("amd64", "xmm1lq"): 256,
    ("amd64", "xmm1hq"): 264,
    ("amd64", "ymm1hx"): 272,
    ("amd64", "ymm2"): 288,
    ("amd64", "xmm2"): 288,
    ("amd64", "xmm2lq"): 288,
    ("amd64", "xmm2hq"): 296,
    ("amd64", "ymm2hx"): 304,
    ("amd64", "ymm3"): 320,
    ("amd64", "xmm3"): 320,
    ("amd64", "xmm3lq"): 320,
    ("amd64", "xmm3hq"): 328,
    ("amd64", "ymm3hx"): 336,
    ("amd64", "ymm4"): 352,
    ("amd64", "xmm4"): 352,
    ("amd64", "xmm4lq"): 352,
    ("amd64", "xmm4hq"): 360,
    ("amd64", "ymm4hx"): 368,
    ("amd64", "ymm5"): 384,
    ("amd64", "xmm5"): 384,
    ("amd64", "xmm5lq"): 384,
    ("amd64", "xmm5hq"): 392,
    ("amd64", "ymm5hx"): 400,
    ("amd64", "ymm6"): 416,
    ("amd64", "xmm6"): 416,
    ("amd64", "xmm6lq"): 416,
    ("amd64", "xmm6hq"): 424,
    ("amd64", "ymm6hx"): 432,
    ("amd64", "ymm7"): 448,
    ("amd64", "xmm7"): 448,
    ("amd64", "xmm7lq"): 448,
    ("amd64", "xmm7hq"): 456,
    ("amd64", "ymm7hx"): 464,
    ("amd64", "ymm8"): 480,
    ("amd64", "xmm8"): 480,
    ("amd64", "xmm8lq"): 480,
    ("amd64", "xmm8hq"): 488,
    ("amd64", "ymm8hx"): 496,
    ("amd64", "ymm9"): 512,
    ("amd64", "xmm9"): 512,
    ("amd64", "xmm9lq"): 512,
    ("amd64", "xmm9hq"): 520,
    ("amd64", "ymm9hx"): 528,
    ("amd64", "ymm10"): 544,
    ("amd64", "xmm10"): 544,
    ("amd64", "xmm10lq"): 544,
    ("amd64", "xmm10hq"): 552,
    ("amd64", "ymm10hx"): 560,
    ("amd64", "ymm11"): 576,
    ("amd64", "xmm11"): 576,
    ("amd64", "xmm11lq"): 576,
    ("amd64", "xmm11hq"): 584,
    ("amd64", "ymm11hx"): 592,
    ("amd64", "ymm12"): 608,
    ("amd64", "xmm12"): 608,
    ("amd64", "xmm12lq"): 608,
    ("amd64", "xmm12hq"): 616,
    ("amd64", "ymm12hx"): 624,
    ("amd64", "ymm13"): 640,
    ("amd64", "xmm13"): 640,
    ("amd64", "xmm13lq"): 640,
    ("amd64", "xmm13hq"): 648,
    ("amd64", "ymm13hx"): 656,
    ("amd64", "ymm14"): 672,
    ("amd64", "xmm14"): 672,
    ("amd64", "xmm14lq"): 672,
    ("amd64", "xmm14hq"): 680,
    ("amd64", "ymm14hx"): 688,
    ("amd64", "ymm15"): 704,
    ("amd64", "xmm15"): 704,
    ("amd64", "xmm15lq"): 704,
    ("amd64", "xmm15hq"): 712,
    ("amd64", "ymm15hx"): 720,
    ("amd64", "ftop"): 896,
    ("amd64", "fpreg"): 904,
    ("amd64", "fpu_regs"): 904,
    ("amd64", "mm0"): 904,
    ("amd64", "mm1"): 912,
    ("amd64", "mm2"): 920,
    ("amd64", "mm3"): 928,
    ("amd64", "mm4"): 936,
    ("amd64", "mm5"): 944,
    ("amd64", "mm6"): 952,
    ("amd64", "mm7"): 960,
    ("amd64", "fptag"): 968,
    ("amd64", "fpu_tags"): 968,
    ("amd64", "fpround"): 976,
    ("amd64", "fc3210"): 984,
    ("amd64", "emnote"): 992,
    ("amd64", "cmstart"): 1000,
    ("amd64", "cmlen"): 1008,
    ("amd64", "nraddr"): 1016,
    ("amd64", "gs"): 1032,
    ("amd64", "gs_const"): 1032,
    ("amd64", "ip_at_syscall"): 1040,
    ("amd64", "cs_seg"): 1048,
    ("amd64", "ds_seg"): 1050,
    ("amd64", "es_seg"): 1052,
    ("amd64", "fs_seg"): 1054,
    ("amd64", "gs_seg"): 1056,
    ("amd64", "ss_seg"): 1058,
    ("arm", "r0"): 8,
    ("arm", "a1"): 8,
    ("arm", "r1"): 12,
    ("arm", "a2"): 12,
    ("arm", "r2"): 16,
    ("arm", "a3"): 16,
    ("arm", "r3"): 20,
    ("arm", "a4"): 20,
    ("arm", "r4"): 24,
    ("arm", "v1"): 24,
    ("arm", "r5"): 28,
    ("arm", "v2"): 28,
    ("arm", "r6"): 32,
    ("arm", "v3"): 32,
    ("arm", "r7"): 36,
    ("arm", "v4"): 36,
    ("arm", "r8"): 40,
    ("arm", "v5"): 40,
    ("arm", "r9"): 44,
    ("arm", "v6"): 44,
    ("arm", "sb"): 44,
    ("arm", "r10"): 48,
    ("arm", "v7"): 48,
    ("arm", "sl"): 48,
    ("arm", "r11"): 52,
    ("arm", "v8"): 52,
    ("arm", "fp"): 52,
    ("arm", "bp"): 52,
    ("arm", "r12"): 56,
    ("arm", "sp"): 60,
    ("arm", "r13"): 60,
    ("arm", "lr"): 64,
    ("arm", "r14"): 64,
    ("arm", "pc"): 68,
    ("arm", "r15"): 68,
    ("arm", "ip"): 68,
    ("arm", "cc_op"): 72,
    ("arm", "cc_dep1"): 76,
    ("arm", "cc_dep2"): 80,
    ("arm", "cc_ndep"): 84,
    ("arm", "qflag32"): 88,
    ("arm", "geflag0"): 92,
    ("arm", "geflag1"): 96,
    ("arm", "geflag2"): 100,
    ("arm", "geflag3"): 104,
    ("arm", "emnote"): 108,
    ("arm", "cmstart"): 112,
    ("arm", "cmlen"): 116,
    ("arm", "nraddr"): 120,
    ("arm", "ip_at_syscall"): 124,
    ("arm", "d0"): 128,
    ("arm", "s0"): 128,
    ("arm", "s1"): 132,
    ("arm", "d1"): 136,
    ("arm", "s2"): 136,
    ("arm", "s3"): 140,
    ("arm", "d2"): 144,
    ("arm", "s4"): 144,
    ("arm", "s5"): 148,
    ("arm", "d3"): 152,
    ("arm", "s6"): 152,
    ("arm", "s7"): 156,
    ("arm", "d4"): 160,
    ("arm", "s8"): 160,
    ("arm", "s9"): 164,
    ("arm", "d5"): 168,
    ("arm", "s10"): 168,
    ("arm", "s11"): 172,
    ("arm", "d6"): 176,
    ("arm", "s12"): 176,
    ("arm", "s13"): 180,
    ("arm", "d7"): 184,
    ("arm", "s14"): 184,
    ("arm", "s15"): 188,
    ("arm", "d8"): 192,
    ("arm", "s16"): 192,
    ("arm", "s17"): 196,
    ("arm", "d9"): 200,
    ("arm", "s18"): 200,
    ("arm", "s19"): 204,
    ("arm", "d10"): 208,
    ("arm", "s20"): 208,
    ("arm", "s21"): 212,
    ("arm", "d11"): 216,
    ("arm", "s22"): 216,
    ("arm", "s23"): 220,
    ("arm", "d12"): 224,
    ("arm", "s24"): 224,
    ("arm", "s25"): 228,
    ("arm", "d13"): 232,
    ("arm", "s26"): 232,
    ("arm", "s27"): 236,
    ("arm", "d14"): 240,
    ("arm", "s28"): 240,
    ("arm", "s29"): 244,
    ("arm", "d15"): 248,
    ("arm", "s30"): 248,
    ("arm", "s31"): 252,
    ("arm", "d16"): 256,
    ("arm", "d17"): 264,
    ("arm", "d18"): 272,
    ("arm", "d19"): 280,
    ("arm", "d20"): 288,
    ("arm", "d21"): 296,
    ("arm", "d22"): 304,
    ("arm", "d23"): 312,
    ("arm", "d24"): 320,
    ("arm", "d25"): 328,
    ("arm", "d26"): 336,
    ("arm", "d27"): 344,
    ("arm", "d28"): 352,
    ("arm", "d29"): 360,
    ("arm", "d30"): 368,
    ("arm", "d31"): 376,
    ("arm", "fpscr"): 384,
    ("arm", "tpidruro"): 388,
    ("arm", "itstate"): 392,
    ("arm64", "x0"): 16,
    ("arm64", "r0"): 16,
    ("arm64", "w0"): 16,
    ("arm64", "x1"): 24,
    ("arm64", "r1"): 24,
    ("arm64", "w1"): 24,
    ("arm64", "x2"): 32,
    ("arm64", "r2"): 32,
    ("arm64", "w2"): 32,
    ("arm64", "x3"): 40,
    ("arm64", "r3"): 40,
    ("arm64", "w3"): 40,
    ("arm64", "x4"): 48,
    ("arm64", "r4"): 48,
    ("arm64", "w4"): 48,
    ("arm64", "x5"): 56,
    ("arm64", "r5"): 56,
    ("arm64", "w5"): 56,
    ("arm64", "x6"): 64,
    ("arm64", "r6"): 64,
    ("arm64", "w6"): 64,
    ("arm64", "x7"): 72,
    ("arm64", "r7"): 72,
    ("arm64", "w7"): 72,
    ("arm64", "x8"): 80,
    ("arm64", "r8"): 80,
    ("arm64", "w8"): 80,
    ("arm64", "x9"): 88,
    ("arm64", "r9"): 88,
    ("arm64", "w9"): 88,
    ("arm64", "x10"): 96,
    ("arm64", "r10"): 96,
    ("arm64", "w10"): 96,
    ("arm64", "x11"): 104,
    ("arm64", "r11"): 104,
    ("arm64", "w11"): 104,
    ("arm64", "x12"): 112,
    ("arm64", "r12"): 112,
    ("arm64", "w12"): 112,
    ("arm64", "x13"): 120,
    ("arm64", "r13"): 120,
    ("arm64", "w13"): 120,
    ("arm64", "x14"): 128,
    ("arm64", "r14"): 128,
    ("arm64", "w14"): 128,
    ("arm64", "x15"): 136,
    ("arm64", "r15"): 136,
    ("arm64", "w15"): 136,
    ("arm64", "x16"): 144,
    ("arm64", "r16"): 144,
    ("arm64", "ip0"): 144,
    ("arm64", "w16"): 144,
    ("arm64", "x17"): 152,
    ("arm64", "r17"): 152,
    ("arm64", "ip1"): 152,
    ("arm64", "w17"): 152,
    ("arm64", "x18"): 160,
    ("arm64", "r18"): 160,
    ("arm64", "w18"): 160,
    ("arm64", "x19"): 168,
    ("arm64", "r19"): 168,
    ("arm64", "w19"): 168,
    ("arm64", "x20"): 176,
    ("arm64", "r20"): 176,
    ("arm64", "w20"): 176,
    ("arm64", "x21"): 184,
    ("arm64", "r21"): 184,
    ("arm64", "w21"): 184,
    ("arm64", "x22"): 192,
    ("arm64", "r22"): 192,
    ("arm64", "w22"): 192,
    ("arm64", "x23"): 200,
    ("arm64", "r23"): 200,
    ("arm64", "w23"): 200,
    ("arm64", "x24"): 208,
    ("arm64", "r24"): 208,
    ("arm64", "w24"): 208,
    ("arm64", "x25"): 216,
    ("arm64", "r25"): 216,
    ("arm64", "w25"): 216,
    ("arm64", "x26"): 224,
    ("arm64", "r26"): 224,
    ("arm64", "w26"): 224,
    ("arm64", "x27"): 232,
    ("arm64", "r27"): 232,
    ("arm64", "w27"): 232,
    ("arm64", "x28"): 240,
    ("arm64", "r28"): 240,
    ("arm64", "w28"): 240,
    ("arm64", "x29"): 248,
    ("arm64", "r29"): 248,
    ("arm64", "fp"): 248,
    ("arm64", "bp"): 248,
    ("arm64", "w29"): 248,
    ("arm64", "x30"): 256,
    ("arm64", "r30"): 256,
    ("arm64", "lr"): 256,
    ("arm64", "w30"): 256,
    ("arm64", "xsp"): 264,
    ("arm64", "sp"): 264,
    ("arm64", "wsp"): 264,
    ("arm64", "pc"): 272,
    ("arm64", "ip"): 272,
    ("arm64", "cc_op"): 280,
    ("arm64", "cc_dep1"): 288,
    ("arm64", "cc_dep2"): 296,
    ("arm64", "cc_ndep"): 304,
    ("arm64", "tpidr_el0"): 312,
    ("arm64", "q0"): 320,
    ("arm64", "v0"): 320,
    ("arm64", "d0"): 320,
    ("arm64", "s0"): 320,
    ("arm64", "h0"): 320,
    ("arm64", "b0"): 320,
    ("arm64", "q1"): 336,
    ("arm64", "v1"): 336,
    ("arm64", "d1"): 336,
    ("arm64", "s1"): 336,
    ("arm64", "h1"): 336,
    ("arm64", "b1"): 336,
    ("arm64", "q2"): 352,
    ("arm64", "v2"): 352,
    ("arm64", "d2"): 352,
    ("arm64", "s2"): 352,
    ("arm64", "h2"): 352,
    ("arm64", "b2"): 352,
    ("arm64", "q3"): 368,
    ("arm64", "v3"): 368,
    ("arm64", "d3"): 368,
    ("arm64", "s3"): 368,
    ("arm64", "h3"): 368,
    ("arm64", "b3"): 368,
    ("arm64", "q4"): 384,
    ("arm64", "v4"): 384,
    ("arm64", "d4"): 384,
    ("arm64", "s4"): 384,
    ("arm64", "h4"): 384,
    ("arm64", "b4"): 384,
    ("arm64", "q5"): 400,
    ("arm64", "v5"): 400,
    ("arm64", "d5"): 400,
    ("arm64", "s5"): 400,
    ("arm64", "h5"): 400,
    ("arm64", "b5"): 400,
    ("arm64", "q6"): 416,
    ("arm64", "v6"): 416,
    ("arm64", "d6"): 416,
    ("arm64", "s6"): 416,
    ("arm64", "h6"): 416,
    ("arm64", "b6"): 416,
    ("arm64", "q7"): 432,
    ("arm64", "v7"): 432,
    ("arm64", "d7"): 432,
    ("arm64", "s7"): 432,
    ("arm64", "h7"): 432,
    ("arm64", "b7"): 432,
    ("arm64", "q8"): 448,
    ("arm64", "v8"): 448,
    ("arm64", "d8"): 448,
    ("arm64", "s8"): 448,
    ("arm64", "h8"): 448,
    ("arm64", "b8"): 448,
    ("arm64", "q9"): 464,
    ("arm64", "v9"): 464,
    ("arm64", "d9"): 464,
    ("arm64", "s9"): 464,
    ("arm64", "h9"): 464,
    ("arm64", "b9"): 464,
    ("arm64", "q10"): 480,
    ("arm64", "v10"): 480,
    ("arm64", "d10"): 480,
    ("arm64", "s10"): 480,
    ("arm64", "h10"): 480,
    ("arm64", "b10"): 480,
    ("arm64", "q11"): 496,
    ("arm64", "v11"): 496,
    ("arm64", "d11"): 496,
    ("arm64", "s11"): 496,
    ("arm64", "h11"): 496,
    ("arm64", "b11"): 496,
    ("arm64", "q12"): 512,
    ("arm64", "v12"): 512,
    ("arm64", "d12"): 512,
    ("arm64", "s12"): 512,
    ("arm64", "h12"): 512,
    ("arm64", "b12"): 512,
    ("arm64", "q13"): 528,
    ("arm64", "v13"): 528,
    ("arm64", "d13"): 528,
    ("arm64", "s13"): 528,
    ("arm64", "h13"): 528,
    ("arm64", "b13"): 528,
    ("arm64", "q14"): 544,
    ("arm64", "v14"): 544,
    ("arm64", "d14"): 544,
    ("arm64", "s14"): 544,
    ("arm64", "h14"): 544,
    ("arm64", "b14"): 544,
    ("arm64", "q15"): 560,
    ("arm64", "v15"): 560,
    ("arm64", "d15"): 560,
    ("arm64", "s15"): 560,
    ("arm64", "h15"): 560,
    ("arm64", "b15"): 560,
    ("arm64", "q16"): 576,
    ("arm64", "v16"): 576,
    ("arm64", "d16"): 576,
    ("arm64", "s16"): 576,
    ("arm64", "h16"): 576,
    ("arm64", "b16"): 576,
    ("arm64", "q17"): 592,
    ("arm64", "v17"): 592,
    ("arm64", "d17"): 592,
    ("arm64", "s17"): 592,
    ("arm64", "h17"): 592,
    ("arm64", "b17"): 592,
    ("arm64", "q18"): 608,
    ("arm64", "v18"): 608,
    ("arm64", "d18"): 608,
    ("arm64", "s18"): 608,
    ("arm64", "h18"): 608,
    ("arm64", "b18"): 608,
    ("arm64", "q19"): 624,
    ("arm64", "v19"): 624,
    ("arm64", "d19"): 624,
    ("arm64", "s19"): 624,
    ("arm64", "h19"): 624,
    ("arm64", "b19"): 624,
    ("arm64", "q20"): 640,
    ("arm64", "v20"): 640,
    ("arm64", "d20"): 640,
    ("arm64", "s20"): 640,
    ("arm64", "h20"): 640,
    ("arm64", "b20"): 640,
    ("arm64", "q21"): 656,
    ("arm64", "v21"): 656,
    ("arm64", "d21"): 656,
    ("arm64", "s21"): 656,
    ("arm64", "h21"): 656,
    ("arm64", "b21"): 656,
    ("arm64", "q22"): 672,
    ("arm64", "v22"): 672,
    ("arm64", "d22"): 672,
    ("arm64", "s22"): 672,
    ("arm64", "h22"): 672,
    ("arm64", "b22"): 672,
    ("arm64", "q23"): 688,
    ("arm64", "v23"): 688,
    ("arm64", "d23"): 688,
    ("arm64", "s23"): 688,
    ("arm64", "h23"): 688,
    ("arm64", "b23"): 688,
    ("arm64", "q24"): 704,
    ("arm64", "v24"): 704,
    ("arm64", "d24"): 704,
    ("arm64", "s24"): 704,
    ("arm64", "h24"): 704,
    ("arm64", "b24"): 704,
    ("arm64", "q25"): 720,
    ("arm64", "v25"): 720,
    ("arm64", "d25"): 720,
    ("arm64", "s25"): 720,
    ("arm64", "h25"): 720,
    ("arm64", "b25"): 720,
    ("arm64", "q26"): 736,
    ("arm64", "v26"): 736,
    ("arm64", "d26"): 736,
    ("arm64", "s26"): 736,
    ("arm64", "h26"): 736,
    ("arm64", "b26"): 736,
    ("arm64", "q27"): 752,
    ("arm64", "v27"): 752,
    ("arm64", "d27"): 752,
    ("arm64", "s27"): 752,
    ("arm64", "h27"): 752,
    ("arm64", "b27"): 752,
    ("arm64", "q28"): 768,
    ("arm64", "v28"): 768,
    ("arm64", "d28"): 768,
    ("arm64", "s28"): 768,
    ("arm64", "h28"): 768,
    ("arm64", "b28"): 768,
    ("arm64", "q29"): 784,
    ("arm64", "v29"): 784,
    ("arm64", "d29"): 784,
    ("arm64", "s29"): 784,
    ("arm64", "h29"): 784,
    ("arm64", "b29"): 784,
    ("arm64", "q30"): 800,
    ("arm64", "v30"): 800,
    ("arm64", "d30"): 800,
    ("arm64", "s30"): 800,
    ("arm64", "h30"): 800,
    ("arm64", "b30"): 800,
    ("arm64", "q31"): 816,
    ("arm64", "v31"): 816,
    ("arm64", "d31"): 816,
    ("arm64", "s31"): 816,
    ("arm64", "h31"): 816,
    ("arm64", "b31"): 816,
    ("arm64", "qcflag"): 832,
    ("arm64", "emnote"): 848,
    ("arm64", "cmstart"): 856,
    ("arm64", "cmlen"): 864,
    ("arm64", "nraddr"): 872,
    ("arm64", "ip_at_syscall"): 880,
    ("arm64", "fpcr"): 888,
    ("ppc32", "gpr0"): 16,
    ("ppc32", "r0"): 16,
    ("ppc32", "gpr1"): 20,
    ("ppc32", "r1"): 20,
    ("ppc32", "sp"): 20,
    ("ppc32", "gpr2"): 24,
    ("ppc32", "r2"): 24,
    ("ppc32", "gpr3"): 28,
    ("ppc32", "r3"): 28,
    ("ppc32", "gpr4"): 32,
    ("ppc32", "r4"): 32,
    ("ppc32", "gpr5"): 36,
    ("ppc32", "r5"): 36,
    ("ppc32", "gpr6"): 40,
    ("ppc32", "r6"): 40,
    ("ppc32", "gpr7"): 44,
    ("ppc32", "r7"): 44,
    ("ppc32", "gpr8"): 48,
    ("ppc32", "r8"): 48,
    ("ppc32", "gpr9"): 52,
    ("ppc32", "r9"): 52,
    ("ppc32", "gpr10"): 56,
    ("ppc32", "r10"): 56,
    ("ppc32", "gpr11"): 60,
    ("ppc32", "r11"): 60,
    ("ppc32", "gpr12"): 64,
    ("ppc32", "r12"): 64,
    ("ppc32", "gpr13"): 68,
    ("ppc32", "r13"): 68,
    ("ppc32", "gpr14"): 72,
    ("ppc32", "r14"): 72,
    ("ppc32", "gpr15"): 76,
    ("ppc32", "r15"): 76,
    ("ppc32", "gpr16"): 80,
    ("ppc32", "r16"): 80,
    ("ppc32", "gpr17"): 84,
    ("ppc32", "r17"): 84,
    ("ppc32", "gpr18"): 88,
    ("ppc32", "r18"): 88,
    ("ppc32", "gpr19"): 92,
    ("ppc32", "r19"): 92,
    ("ppc32", "gpr20"): 96,
    ("ppc32", "r20"): 96,
    ("ppc32", "gpr21"): 100,
    ("ppc32", "r21"): 100,
    ("ppc32", "gpr22"): 104,
    ("ppc32", "r22"): 104,
    ("ppc32", "gpr23"): 108,
    ("ppc32", "r23"): 108,
    ("ppc32", "gpr24"): 112,
    ("ppc32", "r24"): 112,
    ("ppc32", "gpr25"): 116,
    ("ppc32", "r25"): 116,
    ("ppc32", "gpr26"): 120,
    ("ppc32", "r26"): 120,
    ("ppc32", "gpr27"): 124,
    ("ppc32", "r27"): 124,
    ("ppc32", "gpr28"): 128,
    ("ppc32", "r28"): 128,
    ("ppc32", "gpr29"): 132,
    ("ppc32", "r29"): 132,
    ("ppc32", "gpr30"): 136,
    ("ppc32", "r30"): 136,
    ("ppc32", "gpr31"): 140,
    ("ppc32", "r31"): 140,
    ("ppc32", "bp"): 140,
    ("ppc32", "vsr0"): 144,
    ("ppc32", "v0"): 144,
    ("ppc32", "fpr0"): 144,
    ("ppc32", "vsr1"): 160,
    ("ppc32", "v1"): 160,
    ("ppc32", "fpr1"): 160,
    ("ppc32", "vsr2"): 176,
    ("ppc32", "v2"): 176,
    ("ppc32", "fpr2"): 176,
    ("ppc32", "vsr3"): 192,
    ("ppc32", "v3"): 192,
    ("ppc32", "fpr3"): 192,
    ("ppc32", "vsr4"): 208,
    ("ppc32", "v4"): 208,
    ("ppc32", "fpr4"): 208,
    ("ppc32", "vsr5"): 224,
    ("ppc32", "v5"): 224,
    ("ppc32", "fpr5"): 224,
    ("ppc32", "vsr6"): 240,
    ("ppc32", "v6"): 240,
    ("ppc32", "fpr6"): 240,
    ("ppc32", "vsr7"): 256,
    ("ppc32", "v7"): 256,
    ("ppc32", "fpr7"): 256,
    ("ppc32", "vsr8"): 272,
    ("ppc32", "v8"): 272,
    ("ppc32", "fpr8"): 272,
    ("ppc32", "vsr9"): 288,
    ("ppc32", "v9"): 288,
    ("ppc32", "fpr9"): 288,
    ("ppc32", "vsr10"): 304,
    ("ppc32", "v10"): 304,
    ("ppc32", "fpr10"): 304,
    ("ppc32", "vsr11"): 320,
    ("ppc32", "v11"): 320,
    ("ppc32", "fpr11"): 320,
    ("ppc32", "vsr12"): 336,
    ("ppc32", "v12"): 336,
    ("ppc32", "fpr12"): 336,
    ("ppc32", "vsr13"): 352,
    ("ppc32", "v13"): 352,
    ("ppc32", "fpr13"): 352,
    ("ppc32", "vsr14"): 368,
    ("ppc32", "v14"): 368,
    ("ppc32", "fpr14"): 368,
    ("ppc32", "vsr15"): 384,
    ("ppc32", "v15"): 384,
    ("ppc32", "fpr15"): 384,
    ("ppc32", "vsr16"): 400,
    ("ppc32", "v16"): 400,
    ("ppc32", "fpr16"): 400,
    ("ppc32", "vsr17"): 416,
    ("ppc32", "v17"): 416,
    ("ppc32", "fpr17"): 416,
    ("ppc32", "vsr18"): 432,
    ("ppc32", "v18"): 432,
    ("ppc32", "fpr18"): 432,
    ("ppc32", "vsr19"): 448,
    ("ppc32", "v19"): 448,
    ("ppc32", "fpr19"): 448,
    ("ppc32", "vsr20"): 464,
    ("ppc32", "v20"): 464,
    ("ppc32", "fpr20"): 464,
    ("ppc32", "vsr21"): 480,
    ("ppc32", "v21"): 480,
    ("ppc32", "fpr21"): 480,
    ("ppc32", "vsr22"): 496,
    ("ppc32", "v22"): 496,
    ("ppc32", "fpr22"): 496,
    ("ppc32", "vsr23"): 512,
    ("ppc32", "v23"): 512,
    ("ppc32", "fpr23"): 512,
    ("ppc32", "vsr24"): 528,
    ("ppc32", "v24"): 528,
    ("ppc32", "fpr24"): 528,
    ("ppc32", "vsr25"): 544,
    ("ppc32", "v25"): 544,
    ("ppc32", "fpr25"): 544,
    ("ppc32", "vsr26"): 560,
    ("ppc32", "v26"): 560,
    ("ppc32", "fpr26"): 560,
    ("ppc32", "vsr27"): 576,
    ("ppc32", "v27"): 576,
    ("ppc32", "fpr27"): 576,
    ("ppc32", "vsr28"): 592,
    ("ppc32", "v28"): 592,
    ("ppc32", "fpr28"): 592,
    ("ppc32", "vsr29"): 608,
    ("ppc32", "v29"): 608,
    ("ppc32", "fpr29"): 608,
    ("ppc32", "vsr30"): 624,
    ("ppc32", "v30"): 624,
    ("ppc32", "fpr30"): 624,
    ("ppc32", "vsr31"): 640,
    ("ppc32", "v31"): 640,
    ("ppc32", "fpr31"): 640,
    ("ppc32", "vsr32"): 656,
    ("ppc32", "v32"): 656,
    ("ppc32", "vsr33"): 672,
    ("ppc32", "v33"): 672,
    ("ppc32", "vsr34"): 688,
    ("ppc32", "v34"): 688,
    ("ppc32", "vsr35"): 704,
    ("ppc32", "v35"): 704,
    ("ppc32", "vsr36"): 720,
    ("ppc32", "v36"): 720,
    ("ppc32", "vsr37"): 736,
    ("ppc32", "v37"): 736,
    ("ppc32", "vsr38"): 752,
    ("ppc32", "v38"): 752,
    ("ppc32", "vsr39"): 768,
    ("ppc32", "v39"): 768,
    ("ppc32", "vsr40"): 784,
    ("ppc32", "v40"): 784,
    ("ppc32", "vsr41"): 800,
    ("ppc32", "v41"): 800,
    ("ppc32", "vsr42"): 816,
    ("ppc32", "v42"): 816,
    ("ppc32", "vsr43"): 832,
    ("ppc32", "v43"): 832,
    ("ppc32", "vsr44"): 848,
    ("ppc32", "v44"): 848,
    ("ppc32", "vsr45"): 864,
    ("ppc32", "v45"): 864,
    ("ppc32", "vsr46"): 880,
    ("ppc32", "v46"): 880,
    ("ppc32", "vsr47"): 896,
    ("ppc32", "v47"): 896,
    ("ppc32", "vsr48"): 912,
    ("ppc32", "v48"): 912,
    ("ppc32", "vsr49"): 928,
    ("ppc32", "v49"): 928,
    ("ppc32", "vsr50"): 944,
    ("ppc32", "v50"): 944,
    ("ppc32", "vsr51"): 960,
    ("ppc32", "v51"): 960,
    ("ppc32", "vsr52"): 976,
    ("ppc32", "v52"): 976,
    ("ppc32", "vsr53"): 992,
    ("ppc32", "v53"): 992,
    ("ppc32", "vsr54"): 1008,
    ("ppc32", "v54"): 1008,
    ("ppc32", "vsr55"): 1024,
    ("ppc32", "v55"): 1024,
    ("ppc32", "vsr56"): 1040,
    ("ppc32", "v56"): 1040,
    ("ppc32", "vsr57"): 1056,
    ("ppc32", "v57"): 1056,
    ("ppc32", "vsr58"): 1072,
    ("ppc32", "v58"): 1072,
    ("ppc32", "vsr59"): 1088,
    ("ppc32", "v59"): 1088,
    ("ppc32", "vsr60"): 1104,
    ("ppc32", "v60"): 1104,
    ("ppc32", "vsr61"): 1120,
    ("ppc32", "v61"): 1120,
    ("ppc32", "vsr62"): 1136,
    ("ppc32", "v62"): 1136,
    ("ppc32", "vsr63"): 1152,
    ("ppc32", "v63"): 1152,
    ("ppc32", "cia"): 1168,
    ("ppc32", "ip"): 1168,
    ("ppc32", "pc"): 1168,
    ("ppc32", "lr"): 1172,
    ("ppc32", "ctr"): 1176,
    ("ppc32", "xer_so"): 1180,
    ("ppc32", "xer_ov"): 1181,
    ("ppc32", "xer_ca"): 1182,
    ("ppc32", "xer_bc"): 1183,
    ("ppc32", "cr0_321"): 1184,
    ("ppc32", "cr0_0"): 1185,
    ("ppc32", "cr0"): 1185,
    ("ppc32", "cr1_321"): 1186,
    ("ppc32", "cr1_0"): 1187,
    ("ppc32", "cr1"): 1187,
    ("ppc32", "cr2_321"): 1188,
    ("ppc32", "cr2_0"): 1189,
    ("ppc32", "cr2"): 1189,
    ("ppc32", "cr3_321"): 1190,
    ("ppc32", "cr3_0"): 1191,
    ("ppc32", "cr3"): 1191,
    ("ppc32", "cr4_321"): 1192,
    ("ppc32", "cr4_0"): 1193,
    ("ppc32", "cr4"): 1193,
    ("ppc32", "cr5_321"): 1194,
    ("ppc32", "cr5_0"): 1195,
    ("ppc32", "cr5"): 1195,
    ("ppc32", "cr6_321"): 1196,
    ("ppc32", "cr6_0"): 1197,
    ("ppc32", "cr6"): 1197,
    ("ppc32", "cr7_321"): 1198,
    ("ppc32", "cr7_0"): 1199,
    ("ppc32", "cr7"): 1199,
    ("ppc32", "fpround"): 1200,
    ("ppc32", "dfpround"): 1201,
    ("ppc32", "c_fpcc"): 1202,
    ("ppc32", "vrsave"): 1204,
    ("ppc32", "vscr"): 1208,
    ("ppc32", "emnote"): 1212,
    ("ppc32", "cmstart"): 1216,
    ("ppc32", "cmlen"): 1220,
    ("ppc32", "nraddr"): 1224,
    ("ppc32", "nraddr_gpr2"): 1228,
    ("ppc32", "redir_sp"): 1232,
    ("ppc32", "redir_stack"): 1236,
    ("ppc32", "ip_at_syscall"): 1364,
    ("ppc32", "sprg3_ro"): 1368,
    ("ppc32", "tfhar"): 1376,
    ("ppc32", "texasr"): 1384,
    ("ppc32", "tfiar"): 1392,
    ("ppc32", "ppr"): 1400,
    ("ppc32", "texasru"): 1408,
    ("ppc32", "pspb"): 1412,
    ("ppc64", "gpr0"): 16,
    ("ppc64", "r0"): 16,
    ("ppc64", "gpr1"): 24,
    ("ppc64", "r1"): 24,
    ("ppc64", "sp"): 24,
    ("ppc64", "gpr2"): 32,
    ("ppc64", "r2"): 32,
    ("ppc64", "rtoc"): 32,
    ("ppc64", "gpr3"): 40,
    ("ppc64", "r3"): 40,
    ("ppc64", "gpr4"): 48,
    ("ppc64", "r4"): 48,
    ("ppc64", "gpr5"): 56,
    ("ppc64", "r5"): 56,
    ("ppc64", "gpr6"): 64,
    ("ppc64", "r6"): 64,
    ("ppc64", "gpr7"): 72,
    ("ppc64", "r7"): 72,
    ("ppc64", "gpr8"): 80,
    ("ppc64", "r8"): 80,
    ("ppc64", "gpr9"): 88,
    ("ppc64", "r9"): 88,
    ("ppc64", "gpr10"): 96,
    ("ppc64", "r10"): 96,
    ("ppc64", "gpr11"): 104,
    ("ppc64", "r11"): 104,
    ("ppc64", "gpr12"): 112,
    ("ppc64", "r12"): 112,
    ("ppc64", "gpr13"): 120,
    ("ppc64", "r13"): 120,
    ("ppc64", "gpr14"): 128,
    ("ppc64", "r14"): 128,
    ("ppc64", "gpr15"): 136,
    ("ppc64", "r15"): 136,
    ("ppc64", "gpr16"): 144,
    ("ppc64", "r16"): 144,
    ("ppc64", "gpr17"): 152,
    ("ppc64", "r17"): 152,
    ("ppc64", "gpr18"): 160,
    ("ppc64", "r18"): 160,
    ("ppc64", "gpr19"): 168,
    ("ppc64", "r19"): 168,
    ("ppc64", "gpr20"): 176,
    ("ppc64", "r20"): 176,
    ("ppc64", "gpr21"): 184,
    ("ppc64", "r21"): 184,
    ("ppc64", "gpr22"): 192,
    ("ppc64", "r22"): 192,
    ("ppc64", "gpr23"): 200,
    ("ppc64", "r23"): 200,
    ("ppc64", "gpr24"): 208,
    ("ppc64", "r24"): 208,
    ("ppc64", "gpr25"): 216,
    ("ppc64", "r25"): 216,
    ("ppc64", "gpr26"): 224,
    ("ppc64", "r26"): 224,
    ("ppc64", "gpr27"): 232,
    ("ppc64", "r27"): 232,
    ("ppc64", "gpr28"): 240,
    ("ppc64", "r28"): 240,
    ("ppc64", "gpr29"): 248,
    ("ppc64", "r29"): 248,
    ("ppc64", "gpr30"): 256,
    ("ppc64", "r30"): 256,
    ("ppc64", "gpr31"): 264,
    ("ppc64", "r31"): 264,
    ("ppc64", "bp"): 264,
    ("ppc64", "vsr0"): 272,
    ("ppc64", "v0"): 272,
    ("ppc64", "fpr0"): 272,
    ("ppc64", "vsr1"): 288,
    ("ppc64", "v1"): 288,
    ("ppc64", "fpr1"): 288,
    ("ppc64", "vsr2"): 304,
    ("ppc64", "v2"): 304,
    ("ppc64", "fpr2"): 304,
    ("ppc64", "vsr3"): 320,
    ("ppc64", "v3"): 320,
    ("ppc64", "fpr3"): 320,
    ("ppc64", "vsr4"): 336,
    ("ppc64", "v4"): 336,
    ("ppc64", "fpr4"): 336,
    ("ppc64", "vsr5"): 352,
    ("ppc64", "v5"): 352,
    ("ppc64", "fpr5"): 352,
    ("ppc64", "vsr6"): 368,
    ("ppc64", "v6"): 368,
    ("ppc64", "fpr6"): 368,
    ("ppc64", "vsr7"): 384,
    ("ppc64", "v7"): 384,
    ("ppc64", "fpr7"): 384,
    ("ppc64", "vsr8"): 400,
    ("ppc64", "v8"): 400,
    ("ppc64", "fpr8"): 400,
    ("ppc64", "vsr9"): 416,
    ("ppc64", "v9"): 416,
    ("ppc64", "fpr9"): 416,
    ("ppc64", "vsr10"): 432,
    ("ppc64", "v10"): 432,
    ("ppc64", "fpr10"): 432,
    ("ppc64", "vsr11"): 448,
    ("ppc64", "v11"): 448,
    ("ppc64", "fpr11"): 448,
    ("ppc64", "vsr12"): 464,
    ("ppc64", "v12"): 464,
    ("ppc64", "fpr12"): 464,
    ("ppc64", "vsr13"): 480,
    ("ppc64", "v13"): 480,
    ("ppc64", "fpr13"): 480,
    ("ppc64", "vsr14"): 496,
    ("ppc64", "v14"): 496,
    ("ppc64", "fpr14"): 496,
    ("ppc64", "vsr15"): 512,
    ("ppc64", "v15"): 512,
    ("ppc64", "fpr15"): 512,
    ("ppc64", "vsr16"): 528,
    ("ppc64", "v16"): 528,
    ("ppc64", "fpr16"): 528,
    ("ppc64", "vsr17"): 544,
    ("ppc64", "v17"): 544,
    ("ppc64", "fpr17"): 544,
    ("ppc64", "vsr18"): 560,
    ("ppc64", "v18"): 560,
    ("ppc64", "fpr18"): 560,
    ("ppc64", "vsr19"): 576,
    ("ppc64", "v19"): 576,
    ("ppc64", "fpr19"): 576,
    ("ppc64", "vsr20"): 592,
    ("ppc64", "v20"): 592,
    ("ppc64", "fpr20"): 592,
    ("ppc64", "vsr21"): 608,
    ("ppc64", "v21"): 608,
    ("ppc64", "fpr21"): 608,
    ("ppc64", "vsr22"): 624,
    ("ppc64", "v22"): 624,
    ("ppc64", "fpr22"): 624,
    ("ppc64", "vsr23"): 640,
    ("ppc64", "v23"): 640,
    ("ppc64", "fpr23"): 640,
    ("ppc64", "vsr24"): 656,
    ("ppc64", "v24"): 656,
    ("ppc64", "fpr24"): 656,
    ("ppc64", "vsr25"): 672,
    ("ppc64", "v25"): 672,
    ("ppc64", "fpr25"): 672,
    ("ppc64", "vsr26"): 688,
    ("ppc64", "v26"): 688,
    ("ppc64", "fpr26"): 688,
    ("ppc64", "vsr27"): 704,
    ("ppc64", "v27"): 704,
    ("ppc64", "fpr27"): 704,
    ("ppc64", "vsr28"): 720,
    ("ppc64", "v28"): 720,
    ("ppc64", "fpr28"): 720,
    ("ppc64", "vsr29"): 736,
    ("ppc64", "v29"): 736,
    ("ppc64", "fpr29"): 736,
    ("ppc64", "vsr30"): 752,
    ("ppc64", "v30"): 752,
    ("ppc64", "fpr30"): 752,
    ("ppc64", "vsr31"): 768,
    ("ppc64", "v31"): 768,
    ("ppc64", "fpr31"): 768,
    ("ppc64", "vsr32"): 784,
    ("ppc64", "v32"): 784,
    ("ppc64", "vsr33"): 800,
    ("ppc64", "v33"): 800,
    ("ppc64", "vsr34"): 816,
    ("ppc64", "v34"): 816,
    ("ppc64", "vsr35"): 832,
    ("ppc64", "v35"): 832,
    ("ppc64", "vsr36"): 848,
    ("ppc64", "v36"): 848,
    ("ppc64", "vsr37"): 864,
    ("ppc64", "v37"): 864,
    ("ppc64", "vsr38"): 880,
    ("ppc64", "v38"): 880,
    ("ppc64", "vsr39"): 896,
    ("ppc64", "v39"): 896,
    ("ppc64", "vsr40"): 912,
    ("ppc64", "v40"): 912,
    ("ppc64", "vsr41"): 928,
    ("ppc64", "v41"): 928,
    ("ppc64", "vsr42"): 944,
    ("ppc64", "v42"): 944,
    ("ppc64", "vsr43"): 960,
    ("ppc64", "v43"): 960,
    ("ppc64", "vsr44"): 976,
    ("ppc64", "v44"): 976,
    ("ppc64", "vsr45"): 992,
    ("ppc64", "v45"): 992,
    ("ppc64", "vsr46"): 1008,
    ("ppc64", "v46"): 1008,
    ("ppc64", "vsr47"): 1024,
    ("ppc64", "v47"): 1024,
    ("ppc64", "vsr48"): 1040,
    ("ppc64", "v48"): 1040,
    ("ppc64", "vsr49"): 1056,
    ("ppc64", "v49"): 1056,
    ("ppc64", "vsr50"): 1072,
    ("ppc64", "v50"): 1072,
    ("ppc64", "vsr51"): 1088,
    ("ppc64", "v51"): 1088,
    ("ppc64", "vsr52"): 1104,
    ("ppc64", "v52"): 1104,
    ("ppc64", "vsr53"): 1120,
    ("ppc64", "v53"): 1120,
    ("ppc64", "vsr54"): 1136,
    ("ppc64", "v54"): 1136,
    ("ppc64", "vsr55"): 1152,
    ("ppc64", "v55"): 1152,
    ("ppc64", "vsr56"): 1168,
    ("ppc64", "v56"): 1168,
    ("ppc64", "vsr57"): 1184,
    ("ppc64", "v57"): 1184,
    ("ppc64", "vsr58"): 1200,
    ("ppc64", "v58"): 1200,
    ("ppc64", "vsr59"): 1216,
    ("ppc64", "v59"): 1216,
    ("ppc64", "vsr60"): 1232,
    ("ppc64", "v60"): 1232,
    ("ppc64", "vsr61"): 1248,
    ("ppc64", "v61"): 1248,
    ("ppc64", "vsr62"): 1264,
    ("ppc64", "v62"): 1264,
    ("ppc64", "vsr63"): 1280,
    ("ppc64", "v63"): 1280,
    ("ppc64", "cia"): 1296,
    ("ppc64", "ip"): 1296,
    ("ppc64", "pc"): 1296,
    ("ppc64", "lr"): 1304,
    ("ppc64", "ctr"): 1312,
    ("ppc64", "xer_so"): 1320,
    ("ppc64", "xer_ov"): 1321,
    ("ppc64", "xer_ca"): 1322,
    ("ppc64", "xer_bc"): 1323,
    ("ppc64", "cr0_321"): 1324,
    ("ppc64", "cr0_0"): 1325,
    ("ppc64", "cr0"): 1325,
    ("ppc64", "cr1_321"): 1326,
    ("ppc64", "cr1_0"): 1327,
    ("ppc64", "cr1"): 1327,
    ("ppc64", "cr2_321"): 1328,
    ("ppc64", "cr2_0"): 1329,
    ("ppc64", "cr2"): 1329,
    ("ppc64", "cr3_321"): 1330,
    ("ppc64", "cr3_0"): 1331,
    ("ppc64", "cr3"): 1331,
    ("ppc64", "cr4_321"): 1332,
    ("ppc64", "cr4_0"): 1333,
    ("ppc64", "cr4"): 1333,
    ("ppc64", "cr5_321"): 1334,
    ("ppc64", "cr5_0"): 1335,
    ("ppc64", "cr5"): 1335,
    ("ppc64", "cr6_321"): 1336,
    ("ppc64", "cr6_0"): 1337,
    ("ppc64", "cr6"): 1337,
    ("ppc64", "cr7_321"): 1338,
    ("ppc64", "cr7_0"): 1339,
    ("ppc64", "cr7"): 1339,
    ("ppc64", "fpround"): 1340,
    ("ppc64", "dfpround"): 1341,
    ("ppc64", "c_fpcc"): 1342,
    ("ppc64", "vrsave"): 1344,
    ("ppc64", "vscr"): 1348,
    ("ppc64", "emnote"): 1352,
    ("ppc64", "cmstart"): 1360,
    ("ppc64", "cmlen"): 1368,
    ("ppc64", "nraddr"): 1376,
    ("ppc64", "nraddr_gpr2"): 1384,
    ("ppc64", "redir_sp"): 1392,
    ("ppc64", "redir_stack"): 1400,
    ("ppc64", "ip_at_syscall"): 1656,
    ("ppc64", "sprg3_ro"): 1664,
    ("ppc64", "tfhar"): 1672,
    ("ppc64", "texasr"): 1680,
    ("ppc64", "tfiar"): 1688,
    ("ppc64", "ppr"): 1696,
    ("ppc64", "texasru"): 1704,
    ("ppc64", "pspb"): 1708,
    ("s390x", "ia"): 720,
    ("s390x", "ip"): 720,
    ("s390x", "pc"): 720,
    ("s390x", "r0"): 576,
    ("s390x", "r1"): 584,
    ("s390x", "r1_32"): 588,
    ("s390x", "r2"): 592,
    ("s390x", "r2_32"): 596,
    ("s390x", "r3"): 600,
    ("s390x", "r3_32"): 604,
    ("s390x", "r4"): 608,
    ("s390x", "r4_32"): 612,
    ("s390x", "r5"): 616,
    ("s390x", "r5_32"): 620,
    ("s390x", "r6"): 624,
    ("s390x", "r6_32"): 628,
    ("s390x", "r7"): 632,
    ("s390x", "r7_32"): 636,
    ("s390x", "r8"): 640,
    ("s390x", "r8_32"): 644,
    ("s390x", "r9"): 648,
    ("s390x", "r9_32"): 652,
    ("s390x", "r10"): 656,
    ("s390x", "r10_32"): 660,
    ("s390x", "r11"): 664,
    ("s390x", "bp"): 664,
    ("s390x", "r11_32"): 668,
    ("s390x", "r12"): 672,
    ("s390x", "r12_32"): 676,
    ("s390x", "r13"): 680,
    ("s390x", "r13_32"): 684,
    ("s390x", "r14"): 688,
    ("s390x", "lr"): 688,
    ("s390x", "r15"): 696,
    ("s390x", "sp"): 696,
    ("s390x", "v0"): 64,
    ("s390x", "f0"): 64,
    ("s390x", "v1"): 80,
    ("s390x", "f1"): 80,
    ("s390x", "v2"): 96,
    ("s390x", "f2"): 96,
    ("s390x", "v3"): 112,
    ("s390x", "f3"): 112,
    ("s390x", "v4"): 128,
    ("s390x", "f4"): 128,
    ("s390x", "v5"): 144,
    ("s390x", "f5"): 144,
    ("s390x", "v6"): 160,
    ("s390x", "f6"): 160,
    ("s390x", "v7"): 176,
    ("s390x", "f7"): 176,
    ("s390x", "v8"): 192,
    ("s390x", "f8"): 192,
    ("s390x", "v9"): 208,
    ("s390x", "f9"): 208,
    ("s390x", "v10"): 224,
    ("s390x", "f10"): 224,
    ("s390x", "v11"): 240,
    ("s390x", "f11"): 240,
    ("s390x", "v12"): 256,
    ("s390x", "f12"): 256,
    ("s390x", "v13"): 272,
    ("s390x", "f13"): 272,
    ("s390x", "v14"): 288,
    ("s390x", "f14"): 288,
    ("s390x", "v15"): 304,
    ("s390x", "f15"): 304,
    ("s390x", "v16"): 320,
    ("s390x", "v17"): 336,
    ("s390x", "v18"): 352,
    ("s390x", "v19"): 368,
    ("s390x", "v20"): 384,
    ("s390x", "v21"): 400,
    ("s390x", "v22"): 416,
    ("s390x", "v23"): 432,
    ("s390x", "v24"): 448,
    ("s390x", "v25"): 464,
    ("s390x", "v26"): 480,
    ("s390x", "v27"): 496,
    ("s390x", "v28"): 512,
    ("s390x", "v29"): 528,
    ("s390x", "v30"): 544,
    ("s390x", "v31"): 560,
    ("s390x", "a0"): 0,
    ("s390x", "a1"): 4,
    ("s390x", "a2"): 8,
    ("s390x", "a3"): 12,
    ("s390x", "a4"): 16,
    ("s390x", "a5"): 20,
    ("s390x", "a6"): 24,
    ("s390x", "a7"): 28,
    ("s390x", "a8"): 32,
    ("s390x", "a9"): 36,
    ("s390x", "a10"): 40,
    ("s390x", "a11"): 44,
    ("s390x", "a12"): 48,
    ("s390x", "a13"): 52,
    ("s390x", "a14"): 56,
    ("s390x", "a15"): 60,
    ("s390x", "nraddr"): 768,
    ("s390x", "cmstart"): 776,
    ("s390x", "cmlen"): 784,
    ("s390x", "ip_at_syscall"): 792,
    ("s390x", "emnote"): 800,
    ("mips32", "zero"): 8,
    ("mips32", "r0"): 8,
    ("mips32", "at"): 12,
    ("mips32", "r1"): 12,
    ("mips32", "v0"): 16,
    ("mips32", "r2"): 16,
    ("mips32", "v1"): 20,
    ("mips32", "r3"): 20,
    ("mips32", "a0"): 24,
    ("mips32", "r4"): 24,
    ("mips32", "a1"): 28,
    ("mips32", "r5"): 28,
    ("mips32", "a2"): 32,
    ("mips32", "r6"): 32,
    ("mips32", "a3"): 36,
    ("mips32", "r7"): 36,
    ("mips32", "t0"): 40,
    ("mips32", "r8"): 40,
    ("mips32", "t1"): 44,
    ("mips32", "r9"): 44,
    ("mips32", "t2"): 48,
    ("mips32", "r10"): 48,
    ("mips32", "t3"): 52,
    ("mips32", "r11"): 52,
    ("mips32", "t4"): 56,
    ("mips32", "r12"): 56,
    ("mips32", "t5"): 60,
    ("mips32", "r13"): 60,
    ("mips32", "t6"): 64,
    ("mips32", "r14"): 64,
    ("mips32", "t7"): 68,
    ("mips32", "r15"): 68,
    ("mips32", "s0"): 72,
    ("mips32", "r16"): 72,
    ("mips32", "s1"): 76,
    ("mips32", "r17"): 76,
    ("mips32", "s2"): 80,
    ("mips32", "r18"): 80,
    ("mips32", "s3"): 84,
    ("mips32", "r19"): 84,
    ("mips32", "s4"): 88,
    ("mips32", "r20"): 88,
    ("mips32", "s5"): 92,
    ("mips32", "r21"): 92,
    ("mips32", "s6"): 96,
    ("mips32", "r22"): 96,
    ("mips32", "s7"): 100,
    ("mips32", "r23"): 100,
    ("mips32", "t8"): 104,
    ("mips32", "r24"): 104,
    ("mips32", "t9"): 108,
    ("mips32", "r25"): 108,
    ("mips32", "k0"): 112,
    ("mips32", "r26"): 112,
    ("mips32", "k1"): 116,
    ("mips32", "r27"): 116,
    ("mips32", "gp"): 120,
    ("mips32", "r28"): 120,
    ("mips32", "sp"): 124,
    ("mips32", "r29"): 124,
    ("mips32", "s8"): 128,
    ("mips32", "r30"): 128,
    ("mips32", "fp"): 128,
    ("mips32", "bp"): 128,
    ("mips32", "ra"): 132,
    ("mips32", "r31"): 132,
    ("mips32", "lr"): 132,
    ("mips32", "pc"): 136,
    ("mips32", "ip"): 136,
    ("mips32", "hi"): 140,
    ("mips32", "lo"): 144,
    ("mips32", "f0"): 152,
    ("mips32", "f0_lo"): 152,
    ("mips32", "f1"): 160,
    ("mips32", "f1_lo"): 160,
    ("mips32", "f2"): 168,
    ("mips32", "f2_lo"): 168,
    ("mips32", "f3"): 176,
    ("mips32", "f3_lo"): 176,
    ("mips32", "f4"): 184,
    ("mips32", "f4_lo"): 184,
    ("mips32", "f5"): 192,
    ("mips32", "f5_lo"): 192,
    ("mips32", "f6"): 200,
    ("mips32", "f6_lo"): 200,
    ("mips32", "f7"): 208,
    ("mips32", "f7_lo"): 208,
    ("mips32", "f8"): 216,
    ("mips32", "f8_lo"): 216,
    ("mips32", "f9"): 224,
    ("mips32", "f9_lo"): 224,
    ("mips32", "f10"): 232,
    ("mips32", "f10_lo"): 232,
    ("mips32", "f11"): 240,
    ("mips32", "f11_lo"): 240,
    ("mips32", "f12"): 248,
    ("mips32", "f12_lo"): 248,
    ("mips32", "f13"): 256,
    ("mips32", "f13_lo"): 256,
    ("mips32", "f14"): 264,
    ("mips32", "f14_lo"): 264,
    ("mips32", "f15"): 272,
    ("mips32", "f15_lo"): 272,
    ("mips32", "f16"): 280,
    ("mips32", "f16_lo"): 280,
    ("mips32", "f17"): 288,
    ("mips32", "f17_lo"): 288,
    ("mips32", "f18"): 296,
    ("mips32", "f18_lo"): 296,
    ("mips32", "f19"): 304,
    ("mips32", "f19_lo"): 304,
    ("mips32", "f20"): 312,
    ("mips32", "f20_lo"): 312,
    ("mips32", "f21"): 320,
    ("mips32", "f21_lo"): 320,
    ("mips32", "f22"): 328,
    ("mips32", "f22_lo"): 328,
    ("mips32", "f23"): 336,
    ("mips32", "f23_lo"): 336,
    ("mips32", "f24"): 344,
    ("mips32", "f24_lo"): 344,
    ("mips32", "f25"): 352,
    ("mips32", "f25_lo"): 352,
    ("mips32", "f26"): 360,
    ("mips32", "f26_lo"): 360,
    ("mips32", "f27"): 368,
    ("mips32", "f27_lo"): 368,
    ("mips32", "f28"): 376,
    ("mips32", "f28_lo"): 376,
    ("mips32", "f29"): 384,
    ("mips32", "f29_lo"): 384,
    ("mips32", "f30"): 392,
    ("mips32", "f30_lo"): 392,
    ("mips32", "f31"): 400,
    ("mips32", "f31_lo"): 400,
    ("mips32", "fir"): 408,
    ("mips32", "fccr"): 412,
    ("mips32", "fexr"): 416,
    ("mips32", "fenr"): 420,
    ("mips32", "fcsr"): 424,
    ("mips32", "ulr"): 428,
    ("mips32", "emnote"): 432,
    ("mips32", "cmstart"): 436,
    ("mips32", "cmlen"): 440,
    ("mips32", "nraddr"): 444,
    ("mips32", "cond"): 448,
    ("mips32", "dspcontrol"): 452,
    ("mips32", "ac0"): 456,
    ("mips32", "ac1"): 464,
    ("mips32", "ac2"): 472,
    ("mips32", "ac3"): 480,
    ("mips32", "cp0_status"): 488,
    ("mips32", "ip_at_syscall"): 492,
    ("mips64", "zero"): 16,
    ("mips64", "r0"): 16,
    ("mips64", "at"): 24,
    ("mips64", "r1"): 24,
    ("mips64", "v0"): 32,
    ("mips64", "r2"): 32,
    ("mips64", "v1"): 40,
    ("mips64", "r3"): 40,
    ("mips64", "a0"): 48,
    ("mips64", "r4"): 48,
    ("mips64", "a1"): 56,
    ("mips64", "r5"): 56,
    ("mips64", "a2"): 64,
    ("mips64", "r6"): 64,
    ("mips64", "a3"): 72,
    ("mips64", "r7"): 72,
    ("mips64", "t0"): 80,
    ("mips64", "r8"): 80,
    ("mips64", "a4"): 80,
    ("mips64", "t1"): 88,
    ("mips64", "r9"): 88,
    ("mips64", "a5"): 88,
    ("mips64", "t2"): 96,
    ("mips64", "r10"): 96,
    ("mips64", "a6"): 96,
    ("mips64", "t3"): 104,
    ("mips64", "r11"): 104,
    ("mips64", "a7"): 104,
    ("mips64", "t4"): 112,
    ("mips64", "r12"): 112,
    ("mips64", "t5"): 120,
    ("mips64", "r13"): 120,
    ("mips64", "t6"): 128,
    ("mips64", "r14"): 128,
    ("mips64", "t7"): 136,
    ("mips64", "r15"): 136,
    ("mips64", "s0"): 144,
    ("mips64", "r16"): 144,
    ("mips64", "s1"): 152,
    ("mips64", "r17"): 152,
    ("mips64", "s2"): 160,
    ("mips64", "r18"): 160,
    ("mips64", "s3"): 168,
    ("mips64", "r19"): 168,
    ("mips64", "s4"): 176,
    ("mips64", "r20"): 176,
    ("mips64", "s5"): 184,
    ("mips64", "r21"): 184,
    ("mips64", "s6"): 192,
    ("mips64", "r22"): 192,
    ("mips64", "s7"): 200,
    ("mips64", "r23"): 200,
    ("mips64", "t8"): 208,
    ("mips64", "r24"): 208,
    ("mips64", "t9"): 216,
    ("mips64", "r25"): 216,
    ("mips64", "k0"): 224,
    ("mips64", "r26"): 224,
    ("mips64", "k1"): 232,
    ("mips64", "r27"): 232,
    ("mips64", "gp"): 240,
    ("mips64", "r28"): 240,
    ("mips64", "sp"): 248,
    ("mips64", "r29"): 248,
    ("mips64", "s8"): 256,
    ("mips64", "r30"): 256,
    ("mips64", "fp"): 256,
    ("mips64", "bp"): 256,
    ("mips64", "ra"): 264,
    ("mips64", "r31"): 264,
    ("mips64", "lr"): 264,
    ("mips64", "pc"): 272,
    ("mips64", "ip"): 272,
    ("mips64", "hi"): 280,
    ("mips64", "lo"): 288,
    ("mips64", "f0"): 296,
    ("mips64", "f0_lo"): 296,
    ("mips64", "f1"): 304,
    ("mips64", "f1_lo"): 304,
    ("mips64", "f2"): 312,
    ("mips64", "f2_lo"): 312,
    ("mips64", "f3"): 320,
    ("mips64", "f3_lo"): 320,
    ("mips64", "f4"): 328,
    ("mips64", "f4_lo"): 328,
    ("mips64", "f5"): 336,
    ("mips64", "f5_lo"): 336,
    ("mips64", "f6"): 344,
    ("mips64", "f6_lo"): 344,
    ("mips64", "f7"): 352,
    ("mips64", "f7_lo"): 352,
    ("mips64", "f8"): 360,
    ("mips64", "f8_lo"): 360,
    ("mips64", "f9"): 368,
    ("mips64", "f9_lo"): 368,
    ("mips64", "f10"): 376,
    ("mips64", "f10_lo"): 376,
    ("mips64", "f11"): 384,
    ("mips64", "f11_lo"): 384,
    ("mips64", "f12"): 392,
    ("mips64", "f12_lo"): 392,
    ("mips64", "f13"): 400,
    ("mips64", "f13_lo"): 400,
    ("mips64", "f14"): 408,
    ("mips64", "f14_lo"): 408,
    ("mips64", "f15"): 416,
    ("mips64", "f15_lo"): 416,
    ("mips64", "f16"): 424,
    ("mips64", "f16_lo"): 424,
    ("mips64", "f17"): 432,
    ("mips64", "f17_lo"): 432,
    ("mips64", "f18"): 440,
    ("mips64", "f18_lo"): 440,
    ("mips64", "f19"): 448,
    ("mips64", "f19_lo"): 448,
    ("mips64", "f20"): 456,
    ("mips64", "f20_lo"): 456,
    ("mips64", "f21"): 464,
    ("mips64", "f21_lo"): 464,
    ("mips64", "f22"): 472,
    ("mips64", "f22_lo"): 472,
    ("mips64", "f23"): 480,
    ("mips64", "f23_lo"): 480,
    ("mips64", "f24"): 488,
    ("mips64", "f24_lo"): 488,
    ("mips64", "f25"): 496,
    ("mips64", "f25_lo"): 496,
    ("mips64", "f26"): 504,
    ("mips64", "f26_lo"): 504,
    ("mips64", "f27"): 512,
    ("mips64", "f27_lo"): 512,
    ("mips64", "f28"): 520,
    ("mips64", "f28_lo"): 520,
    ("mips64", "f29"): 528,
    ("mips64", "f29_lo"): 528,
    ("mips64", "f30"): 536,
    ("mips64", "f30_lo"): 536,
    ("mips64", "f31"): 544,
    ("mips64", "f31_lo"): 544,
    ("mips64", "fir"): 552,
    ("mips64", "fccr"): 556,
    ("mips64", "fexr"): 560,
    ("mips64", "fenr"): 564,
    ("mips64", "fcsr"): 568,
    ("mips64", "cp0_status"): 572,
    ("mips64", "ulr"): 576,
    ("mips64", "emnote"): 584,
    ("mips64", "cond"): 588,
    ("mips64", "cmstart"): 592,
    ("mips64", "cmlen"): 600,
    ("mips64", "nraddr"): 608,
    ("mips64", "ip_at_syscall"): 616,
    ("riscv64", "x0"): 16,
    ("riscv64", "zero"): 16,
    ("riscv64", "x1"): 24,
    ("riscv64", "ra"): 24,
    ("riscv64", "lr"): 24,
    ("riscv64", "x2"): 32,
    ("riscv64", "sp"): 32,
    ("riscv64", "x3"): 40,
    ("riscv64", "gp"): 40,
    ("riscv64", "x4"): 48,
    ("riscv64", "tp"): 48,
    ("riscv64", "x5"): 56,
    ("riscv64", "t0"): 56,
    ("riscv64", "x6"): 64,
    ("riscv64", "t1"): 64,
    ("riscv64", "x7"): 72,
    ("riscv64", "t2"): 72,
    ("riscv64", "x9"): 88,
    ("riscv64", "s1"): 88,
    ("riscv64", "x10"): 96,
    ("riscv64", "a0"): 96,
    ("riscv64", "x11"): 104,
    ("riscv64", "a1"): 104,
    ("riscv64", "x12"): 112,
    ("riscv64", "a2"): 112,
    ("riscv64", "x13"): 120,
    ("riscv64", "a3"): 120,
    ("riscv64", "x14"): 128,
    ("riscv64", "a4"): 128,
    ("riscv64", "x15"): 136,
    ("riscv64", "a5"): 136,
    ("riscv64", "x16"): 144,
    ("riscv64", "a6"): 144,
    ("riscv64", "x17"): 152,
    ("riscv64", "a7"): 152,
    ("riscv64", "x18"): 160,
    ("riscv64", "s2"): 160,
    ("riscv64", "x19"): 168,
    ("riscv64", "s3"): 168,
    ("riscv64", "x20"): 176,
    ("riscv64", "s4"): 176,
    ("riscv64", "x21"): 184,
    ("riscv64", "s5"): 184,
    ("riscv64", "x22"): 192,
    ("riscv64", "s6"): 192,
    ("riscv64", "x23"): 200,
    ("riscv64", "s7"): 200,
    ("riscv64", "x24"): 208,
    ("riscv64", "s8"): 208,
    ("riscv64", "x25"): 216,
    ("riscv64", "s9"): 216,
    ("riscv64", "x26"): 224,
    ("riscv64", "s10"): 224,
    ("riscv64", "x27"): 232,
    ("riscv64", "s11"): 232,
    ("riscv64", "x28"): 240,
    ("riscv64", "t3"): 240,
    ("riscv64", "x29"): 248,
    ("riscv64", "t4"): 248,
    ("riscv64", "x30"): 256,
    ("riscv64", "t5"): 256,
    ("riscv64", "x31"): 264,
    ("riscv64", "t6"): 264,
    ("riscv64", "pc"): 272,
    ("riscv64", "ip"): 272,
    ("riscv64", "f0"): 280,
    ("riscv64", "ft0"): 280,
    ("riscv64", "f1"): 288,
    ("riscv64", "ft1"): 288,
    ("riscv64", "f2"): 296,
    ("riscv64", "ft2"): 296,
    ("riscv64", "f3"): 304,
    ("riscv64", "ft3"): 304,
    ("riscv64", "f4"): 312,
    ("riscv64", "ft4"): 312,
    ("riscv64", "f5"): 320,
    ("riscv64", "ft5"): 320,
    ("riscv64", "f6"): 328,
    ("riscv64", "ft6"): 328,
    ("riscv64", "f7"): 336,
    ("riscv64", "ft7"): 336,
    ("riscv64", "f9"): 352,
    ("riscv64", "fs1"): 352,
    ("riscv64", "f10"): 360,
    ("riscv64", "fa0"): 360,
    ("riscv64", "f11"): 368,
    ("riscv64", "fa1"): 368,
    ("riscv64", "f12"): 376,
    ("riscv64", "fa2"): 376,
    ("riscv64", "f13"): 384,
    ("riscv64", "fa3"): 384,
    ("riscv64", "f14"): 392,
    ("riscv64", "fa4"): 392,
    ("riscv64", "f15"): 400,
    ("riscv64", "fa5"): 400,
    ("riscv64", "f16"): 408,
    ("riscv64", "fa6"): 408,
    ("riscv64", "f17"): 416,
    ("riscv64", "fa7"): 416,
    ("riscv64", "f18"): 424,
    ("riscv64", "fs2"): 424,
    ("riscv64", "f19"): 432,
    ("riscv64", "fs3"): 432,
    ("riscv64", "f20"): 440,
    ("riscv64", "fs4"): 440,
    ("riscv64", "f21"): 448,
    ("riscv64", "fs5"): 448,
    ("riscv64", "f22"): 456,
    ("riscv64", "fs6"): 456,
    ("riscv64", "f23"): 464,
    ("riscv64", "fs7"): 464,
    ("riscv64", "f24"): 472,
    ("riscv64", "fs8"): 472,
    ("riscv64", "f25"): 480,
    ("riscv64", "fs9"): 480,
    ("riscv64", "f26"): 488,
    ("riscv64", "fs10"): 488,
    ("riscv64", "f27"): 496,
    ("riscv64", "fs11"): 496,
    ("riscv64", "f28"): 504,
    ("riscv64", "ft8"): 504,
    ("riscv64", "f29"): 512,
    ("riscv64", "ft9"): 512,
    ("riscv64", "f30"): 520,
    ("riscv64", "ft10"): 520,
    ("riscv64", "f31"): 528,
    ("riscv64", "ft11"): 528,
}


================================================
FILE: pyvex/arches.py
================================================
from ._register_info import REGISTER_OFFSETS
from .enums import default_vex_archinfo, vex_endness_from_string
from .types import Register
from .vex_ffi import guest_offsets


class PyvexArch:
    """
    An architecture definition for use with pyvex - usable version.
    """

    def __init__(self, name: str, bits: int, memory_endness: str, instruction_endness: str = "Iend_BE"):
        self.name = name
        self.bits = bits
        self.memory_endness = memory_endness
        self.instruction_endness = instruction_endness
        self.byte_width = 8
        self.register_list: list[Register] = []
        self.registers: dict[str, tuple[int, int]] = {}
        self.vex_arch = {
            "X86": "VexArchX86",
            "AMD64": "VexArchAMD64",
            "ARM": "VexArchARM",
            "ARM64": "VexArchARM64",
            "PPC32": "VexArchPPC32",
            "PPC64": "VexArchPPC64",
            "S390X": "VexArchS390X",
            "MIPS32": "VexArchMIPS32",
            "MIPS64": "VexArchMIPS64",
            "RISCV64": "VexArchRISCV64",
        }[name]
        self.ip_offset = guest_offsets[
            (
                self.vex_name_small,
                {
                    "X86": "eip",
                    "AMD64": "rip",
                    "ARM": "r15t",
                    "ARM64": "pc",
                    "PPC32": "cia",
                    "PPC64": "cia",
                    "S390X": "ia",
                    "MIPS32": "pc",
                    "MIPS64": "pc",
                    "RISCV64": "pc",
                }[name],
            )
        ]
        self.vex_archinfo = default_vex_archinfo()
        if memory_endness == "Iend_BE":
            self.vex_archinfo["endness"] = vex_endness_from_string("VexEndnessBE")

    def __repr__(self):
        return f"<PyvexArch {self.name}>"

    @property
    def vex_name_small(self):
        return self.vex_arch[7:].lower()

    def translate_register_name(self, offset, size=None):  # pylint: disable=unused-argument
        for (arch, reg), offset2 in guest_offsets.items():
            if arch == self.vex_name_small and offset2 == offset:
                return reg
        for (arch, reg), offset2 in REGISTER_OFFSETS.items():
            if arch == self.vex_name_small and offset2 == offset:
                return reg
        return str(offset)

    def get_register_offset(self, name: str) -> int:
        arch_reg_tuple = (self.vex_name_small, name)
        if arch_reg_tuple in guest_offsets:
            return guest_offsets[arch_reg_tuple]
        elif arch_reg_tuple in REGISTER_OFFSETS:
            return REGISTER_OFFSETS[arch_reg_tuple]
        else:
            raise KeyError(f"Unknown register {name} for architecture {self.name}")


ARCH_X86 = PyvexArch("X86", 32, "Iend_LE")
ARCH_AMD64 = PyvexArch("AMD64", 64, "Iend_LE")
ARCH_ARM_LE = PyvexArch("ARM", 32, "Iend_LE", instruction_endness="Iend_LE")
ARCH_ARM_BE_LE = PyvexArch("ARM", 32, "Iend_BE", instruction_endness="Iend_LE")
ARCH_ARM_BE = PyvexArch("ARM", 32, "Iend_LE")
ARCH_ARM64_LE = PyvexArch("ARM64", 64, "Iend_LE", instruction_endness="Iend_LE")
ARCH_ARM64_BE = PyvexArch("ARM64", 64, "Iend_BE")
ARCH_PPC32 = PyvexArch("PPC32", 32, "Iend_BE")
ARCH_PPC64_BE = PyvexArch("PPC64", 64, "Iend_BE")
ARCH_PPC64_LE = PyvexArch("PPC64", 64, "Iend_LE")
ARCH_S390X = PyvexArch("S390X", 64, "Iend_BE")
ARCH_MIPS32_BE = PyvexArch("MIPS32", 32, "Iend_BE")
ARCH_MIPS32_LE = PyvexArch("MIPS32", 32, "Iend_LE")
ARCH_MIPS64_BE = PyvexArch("MIPS64", 64, "Iend_BE")
ARCH_MIPS64_LE = PyvexArch("MIPS64", 64, "Iend_LE")
ARCH_RISCV64_LE = PyvexArch("RISCV64", 64, "Iend_LE", instruction_endness="Iend_LE")


================================================
FILE: pyvex/block.py
================================================
import copy
import itertools
import logging
from typing import Optional

from . import expr, stmt
from .const import U1, get_type_size
from .const_val import ConstVal
from .data_ref import DataRef
from .enums import VEXObject
from .errors import SkipStatementsError
from .expr import Const, RdTmp
from .native import pvc
from .stmt import (
    CAS,
    LLSC,
    Dirty,
    Exit,
    IMark,
    IRExpr,
    IRStmt,
    LoadG,
    WrTmp,
    get_enum_from_int,
    get_int_from_enum,
)
from .types import Arch

log = logging.getLogger("pyvex.block")


class IRSB(VEXObject):
    """
    The IRSB is the primary interface to pyvex. Constructing one of these will make a call into LibVEX to perform a
    translation.

    IRSB stands for *Intermediate Representation Super-Block*. An IRSB in VEX is a single-entry, multiple-exit code
    block.

    :ivar arch:             The architecture this block is lifted under. Must duck-type as :class:`archinfo.arch.Arch`
    :ivar statements:       The statements in this block
    :vartype statements:    list of :class:`IRStmt`
    :ivar next:             The expression for the default exit target of this block
    :vartype next:          :class:`IRExpr`
    :ivar int offsIP:       The offset of the instruction pointer in the VEX guest state
    :ivar int stmts_used:   The number of statements in this IRSB
    :ivar str jumpkind:     The type of this block's default jump (call, boring, syscall, etc) as a VEX enum string
    :ivar bool direct_next: Whether this block ends with a direct (not indirect) jump or branch
    :ivar int size:         The size of this block in bytes
    :ivar int addr:         The address of this basic block, i.e. the address in the first IMark
    """

    __slots__ = [
        "addr",
        "arch",
        "statements",
        "next",
        "_tyenv",
        "jumpkind",
        "is_noop_block",
        "_direct_next",
        "_size",
        "_instructions",
        "_exit_statements",
        "default_exit_target",
        "_instruction_addresses",
        "data_refs",
        "const_vals",
    ]

    # The following constants shall match the defs in pyvex.h
    MAX_EXITS = 400
    MAX_DATA_REFS = 2000
    MAX_CONST_VALS = 1000

    def __init__(
        self,
        data,
        mem_addr,
        arch: Arch,
        max_inst=None,
        max_bytes=None,
        bytes_offset=0,
        traceflags=0,
        opt_level=1,
        num_inst=None,
        num_bytes=None,
        strict_block_end=False,
        skip_stmts=False,
        collect_data_refs=False,
        cross_insn_opt=True,
    ):
        """
        :param data:                The bytes to lift. Can be either a string of bytes or a cffi buffer object.
                                    You may also pass None to initialize an empty IRSB.
        :type data:                 str or bytes or cffi.FFI.CData or None
        :param int mem_addr:        The address to lift the data at.
        :param arch:                The architecture to lift the data as.
        :param max_inst:            The maximum number of instructions to lift. (See note below)
        :param max_bytes:           The maximum number of bytes to use.
        :param num_inst:            Replaces max_inst if max_inst is None. If set to None as well, no instruction limit
                                    is used.
        :param num_bytes:           Replaces max_bytes if max_bytes is None. If set to None as well, no  byte limit is
                                    used.
        :param bytes_offset:        The offset into `data` to start lifting at. Note that for ARM THUMB mode, both
                                    `mem_addr` and `bytes_offset` must be odd (typically `bytes_offset` is set to 1).
        :param traceflags:          The libVEX traceflags, controlling VEX debug prints.
        :param opt_level:           The level of optimization to apply to the IR, -1 through 2. -1 is the strictest
                                    unoptimized level, 0 is unoptimized but will perform some lookahead/lookbehind
                                    optimizations, 1 performs constant propogation, and 2 performs loop unrolling,
                                    which honestly doesn't make much sense in the context of pyvex. The default is 1.
        :param strict_block_end:    Should the LibVEX arm-thumb split block at some instructions, for example CB{N}Z.

        .. note:: Explicitly specifying the number of instructions to lift (`max_inst`) may not always work
                  exactly as expected. For example, on MIPS, it is meaningless to lift a branch or jump
                  instruction without its delay slot. VEX attempts to Do The Right Thing by possibly decoding
                  fewer instructions than requested. Specifically, this means that lifting a branch or jump
                  on MIPS as a single instruction (`max_inst=1`) will result in an empty IRSB, and subsequent
                  attempts to run this block will raise `SimIRSBError('Empty IRSB passed to SimIRSB.')`.

        .. note:: If no instruction and byte limit is used, pyvex will continue lifting the block until the block
                  ends properly or until it runs out of data to lift.
        """
        if max_inst is None:
            max_inst = num_inst
        if max_bytes is None:
            max_bytes = num_bytes
        VEXObject.__init__(self)
        self.addr = mem_addr
        self.arch: Arch = arch

        self.statements: list[IRStmt] = []
        self.next: IRExpr = Const(U1(0))
        self._tyenv: Optional["IRTypeEnv"] = None
        self.jumpkind: str = "UNSET"
        self._direct_next: bool | None = None
        self._size: int | None = None
        self._instructions: int | None = None
        self._exit_statements: tuple[tuple[int, int, IRStmt], ...] | None = None
        self.is_noop_block: bool = False
        self.default_exit_target = None
        self.data_refs = ()
        self.const_vals = ()
        self._instruction_addresses: tuple[int, ...] = ()

        if data is not None:
            # This is the slower path (because we need to call _from_py() to copy the content in the returned IRSB to
            # the current IRSB instance. You should always call `lift()` directly. This method is kept for compatibility
            # concerns.
            from pyvex.lifting import lift

            irsb = lift(
                data,
                mem_addr,
                arch,
                max_bytes=max_bytes,
                max_inst=max_inst,
                bytes_offset=bytes_offset,
                opt_level=opt_level,
                traceflags=traceflags,
                strict_block_end=strict_block_end,
                skip_stmts=skip_stmts,
                collect_data_refs=collect_data_refs,
                cross_insn_opt=cross_insn_opt,
            )
            self._from_py(irsb)

    @staticmethod
    def empty_block(arch, addr, statements=None, nxt=None, tyenv=None, jumpkind=None, direct_next=None, size=None):
        block = IRSB(None, addr, arch)
        block._set_attributes(statements, nxt, tyenv, jumpkind, direct_next, size=size)
        return block

    @property
    def tyenv(self) -> "IRTypeEnv":
        if self._tyenv is None:
            self._tyenv = IRTypeEnv(self.arch)
        return self._tyenv

    @tyenv.setter
    def tyenv(self, v):
        self._tyenv = v

    @property
    def has_statements(self) -> bool:
        return self.statements is not None and bool(self.statements)

    @property
    def exit_statements(self) -> tuple[tuple[int, int, IRStmt], ...]:
        if self._exit_statements is not None:
            return self._exit_statements

        # Delayed process
        if not self.has_statements:
            return ()

        exit_statements = []

        ins_addr = None
        for idx, stmt_ in enumerate(self.statements):
            if type(stmt_) is IMark:
                ins_addr = stmt_.addr + stmt_.delta
            elif type(stmt_) is Exit:
                assert ins_addr is not None
                exit_statements.append((ins_addr, idx, stmt_))

        self._exit_statements = tuple(exit_statements)
        return self._exit_statements

    def copy(self) -> "IRSB":
        return copy.deepcopy(self)

    def extend(self, extendwith) -> None:
        """
        Appends an irsb to the current irsb. The irsb that is appended is invalidated. The appended irsb's jumpkind and
        default exit are used.
        :param extendwith:     The IRSB to append to this IRSB
        :vartype extendwith:   :class:`IRSB`
        """
        if self.stmts_used == 0:
            self._from_py(extendwith)
            return

        conversion_dict = {}
        invalid_vals = (0xFFFFFFFF, -1)

        new_size = self.size + extendwith.size
        new_instructions = self.instructions + extendwith.instructions
        new_direct_next = extendwith.direct_next

        def convert_tmp(tmp):
            """
            Converts a tmp from the appended-block into one in the appended-to-block. Creates a new tmp if it does not
            already exist. Prevents collisions in tmp numbers between the two blocks.
            :param tmp:       The tmp number to convert
            """
            if tmp not in conversion_dict:
                tmp_type = extendwith.tyenv.lookup(tmp)
                conversion_dict[tmp] = self.tyenv.add(tmp_type)
            return conversion_dict[tmp]

        def convert_expr(expr_):
            """
            Converts a VEX expression to use tmps in the appended-block instead of the appended-to-block. Used to
            prevent collisions in tmp numbers between the two blocks.
            :param tmp:       The VEX expression to convert
            :vartype expr:    :class:`IRExpr`
            """
            if type(expr_) is RdTmp:
                return RdTmp.get_instance(convert_tmp(expr_.tmp))
            return expr_

        for stmt_ in extendwith.statements:
            stmttype = type(stmt_)
            if stmttype is WrTmp:
                stmt_.tmp = convert_tmp(stmt_.tmp)
            elif stmttype is LoadG:
                stmt_.dst = convert_tmp(stmt_.dst)
            elif stmttype is LLSC:
                stmt_.result = convert_tmp(stmt_.result)
            elif stmttype is Dirty:
                if stmt_.tmp not in invalid_vals:
                    stmt_.tmp = convert_tmp(stmt_.tmp)
                for e in stmt_.args:
                    convert_expr(e)
            elif stmttype is CAS:
                if stmt_.oldLo not in invalid_vals:
                    stmt_.oldLo = convert_tmp(stmt_.oldLo)
                if stmt_.oldHi not in invalid_vals:
                    stmt_.oldHi = convert_tmp(stmt_.oldHi)
            # Convert all expressions
            to_replace = {}
            for expr_ in stmt_.expressions:
                replacement = convert_expr(expr_)
                if replacement is not expr_:
                    to_replace[expr_] = replacement
            stmt_.replace_expression(to_replace)
            # Add the converted statement to self.statements
            self.statements.append(stmt_)
        extendwith.next = convert_expr(extendwith.next)
        self.next = extendwith.next
        self.jumpkind = extendwith.jumpkind
        self._size = new_size
        self._instructions = new_instructions
        self._direct_next = new_direct_next

        # TODO: Change exit_statements, data_references, etc.

    def invalidate_direct_next(self) -> None:
        self._direct_next = None

    def pp(self) -> None:
        """
        Pretty-print the IRSB to stdout.
        """
        print(self._pp_str())

    def __repr__(self):
        return f"IRSB <0x{self.size:x} bytes, {self.instructions} ins., {str(self.arch)}> at 0x{self.addr:x}"

    def __str__(self):
        return self._pp_str()

    def __eq__(self, other):
        return (
            isinstance(other, IRSB)
            and self.addr == other.addr
            and self.arch.name == other.arch.name
            and self.statements == other.statements
            and self.next == other.next
            and self.jumpkind == other.jumpkind
        )

    def __hash__(self):
        return hash((IRSB, self.addr, self.arch.name, tuple(self.statements), self.next, self.jumpkind))

    def typecheck(self) -> bool:
        try:
            # existence assertions
            assert self.next is not None, "Missing next expression"
            assert self.jumpkind is not None, "Missing jumpkind"

            # Type assertions
            assert isinstance(self.next, expr.IRExpr), "Next expression is not an expression"
            assert type(self.jumpkind is str), "Jumpkind is not a string"
            assert self.jumpkind.startswith("Ijk_"), "Jumpkind is not a jumpkind enum"
            assert self.tyenv.typecheck(), "Type environment contains invalid types"

            # statement assertions
            last_imark = None
            for i, st in enumerate(self.statements):
                assert isinstance(st, stmt.IRStmt), "Statement %d is not an IRStmt" % i
                try:
                    assert st.typecheck(self.tyenv), "Statement %d failed to typecheck" % i
                except Exception:  # pylint: disable=bare-except
                    assert False, "Statement %d errored in typechecking" % i

                if type(st) is stmt.NoOp:
                    continue
                elif type(st) is stmt.IMark:
                    if last_imark is not None:
                        # pylint: disable=unsubscriptable-object
                        assert last_imark[0] + last_imark[1] == st.addr, "IMarks sizes overlap or have gaps"
                    last_imark = (st.addr, st.len)
                else:
                    assert last_imark is not None, "Operation statement appears before IMark"

            assert last_imark is not None, "No IMarks present in block"
        except AssertionError as e:
            log.debug(e.args[0])
            return False
        return True

    #
    # alternate constructors
    #

    @staticmethod
    def from_c(c_irsb, mem_addr, arch) -> "IRSB":
        irsb = IRSB(None, mem_addr, arch)
        irsb._from_c(c_irsb)
        return irsb

    @staticmethod
    def from_py(tyenv, stmts, next_expr, jumpkind, mem_addr, arch) -> "IRSB":
        irsb = IRSB(None, mem_addr, arch)

        irsb.tyenv = tyenv
        irsb.statements = stmts
        irsb.next = next_expr
        irsb.jumpkind = jumpkind
        irsb._direct_next = irsb._is_defaultexit_direct_jump()

        return irsb

    #
    # simple properties useful for analysis
    #

    @property
    def stmts_used(self) -> int:
        if self.statements is None:
            return 0
        return len(self.statements)

    @property
    def offsIP(self) -> int:
        return self.arch.ip_offset

    @property
    def direct_next(self):
        if self._direct_next is None:
            self._direct_next = self._is_defaultexit_direct_jump()
        return self._direct_next

    @property
    def expressions(self):
        """
        Return an iterator of all expressions contained in the IRSB.
        """
        for s in self.statements:
            yield from s.expressions
        yield self.next

    @property
    def instructions(self):
        """
        The number of instructions in this block
        """
        if self._instructions is None:
            if self.statements is None:
                self._instructions = 0
            else:
                self._instructions = len([s for s in self.statements if type(s) is stmt.IMark])
        return self._instructions

    @property
    def instruction_addresses(self) -> tuple[int, ...]:
        """
        Addresses of instructions in this block.
        """
        if self._instruction_addresses is None:
            if self.statements is None:
                self._instruction_addresses = ()
            else:
                self._instruction_addresses = tuple(
                    (s.addr + s.delta) for s in self.statements if type(s) is stmt.IMark
                )
        return self._instruction_addresses

    @property
    def size(self):
        """
        The size of this block, in bytes
        """
        if self._size is None:
            self._size = sum(s.len for s in self.statements if type(s) is stmt.IMark)
        return self._size

    @property
    def operations(self):
        """
        A list of all operations done by the IRSB, as libVEX enum names
        """
        ops = []
        for e in self.expressions:
            if hasattr(e, "op"):
                ops.append(e.op)
        return ops

    @property
    def all_constants(self):
        """
        Returns all constants in the block (including incrementing of the program counter) as
        :class:`pyvex.const.IRConst`.
        """
        return sum((e.constants for e in self.expressions), [])

    @property
    def constants(self):
        """
        The constants (excluding updates of the program counter) in the IRSB as :class:`pyvex.const.IRConst`.
        """
        return sum((s.constants for s in self.statements if not (type(s) is stmt.Put and s.offset == self.offsIP)), [])

    @property
    def constant_jump_targets(self):
        """
        A set of the static jump targets of the basic block.
        """
        exits = set()

        if self.exit_statements:
            for _, _, stmt_ in self.exit_statements:
                exits.add(stmt_.dst.value)

        default_target = self.default_exit_target
        if default_target is not None:
            exits.add(default_target)

        return exits

    @property
    def constant_jump_targets_and_jumpkinds(self):
        """
        A dict of the static jump targets of the basic block to their jumpkind.
        """
        exits = {}

        if self.exit_statements:
            for _, _, stmt_ in self.exit_statements:
                exits[stmt_.dst.value] = stmt_.jumpkind

        default_target = self.default_exit_target
        if default_target is not None:
            exits[default_target] = self.jumpkind

        return exits

    #
    # private methods
    #

    def _pp_str(self) -> str:
        """
        Return the pretty-printed IRSB.
        """
        sa = []
        sa.append("IRSB {")
        if self.statements is not None:
            sa.append("   %s" % self.tyenv)
        sa.append("")
        if self.statements is not None:
            for i, s in enumerate(self.statements):
                if isinstance(s, stmt.Put):
                    stmt_str = s.pp_str(
                        reg_name=self.arch.translate_register_name(s.offset, s.data.result_size(self.tyenv) // 8)
                    )
                elif isinstance(s, stmt.WrTmp) and isinstance(s.data, expr.Get):
                    stmt_str = s.pp_str(
                        reg_name=self.arch.translate_register_name(s.data.offset, s.data.result_size(self.tyenv) // 8)
                    )
                elif isinstance(s, stmt.Exit):
                    stmt_str = s.pp_str(reg_name=self.arch.translate_register_name(s.offsIP, self.arch.bits // 8))
                else:
                    stmt_str = s.pp_str()
                sa.append("   %02d | %s" % (i, stmt_str))
        else:
            sa.append("   Statements are omitted.")
        sa.append(f"   NEXT: PUT({self.arch.translate_register_name(self.offsIP)}) = {self.next}; {self.jumpkind}")
        sa.append("}")
        return "\n".join(sa)

    def _is_defaultexit_direct_jump(self):
        """
        Checks if the default of this IRSB a direct jump or not.
        """
        if not (self.jumpkind == "Ijk_InvalICache" or self.jumpkind == "Ijk_Boring" or self.jumpkind == "Ijk_Call"):
            return False

        target = self.default_exit_target
        return target is not None

    #
    # internal "constructors" to fill this block out with data from various sources
    #

    def _from_c(self, lift_r, skip_stmts=False):
        c_irsb = lift_r.irsb
        if not skip_stmts:
            self.statements = [stmt.IRStmt._from_c(c_irsb.stmts[i]) for i in range(c_irsb.stmts_used)]
            self.tyenv = IRTypeEnv._from_c(self.arch, c_irsb.tyenv)
        else:
            self.statements = None
            self.tyenv = None

        self.next = expr.IRExpr._from_c(c_irsb.next)
        self.jumpkind = get_enum_from_int(c_irsb.jumpkind)
        self._size = lift_r.size
        self.is_noop_block = lift_r.is_noop_block == 1
        self._instructions = lift_r.insts
        self._instruction_addresses = tuple(itertools.islice(lift_r.inst_addrs, lift_r.insts))

        # Conditional exits
        exit_statements = []
        if skip_stmts:
            if lift_r.exit_count > self.MAX_EXITS:
                # There are more exits than the default size of the exits array. We will need all statements
                raise SkipStatementsError("exit_count exceeded MAX_EXITS (%d)" % self.MAX_EXITS)
            for i in range(lift_r.exit_count):
                ex = lift_r.exits[i]
                exit_stmt = stmt.IRStmt._from_c(ex.stmt)
                exit_statements.append((ex.ins_addr, ex.stmt_idx, exit_stmt))

            self._exit_statements = tuple(exit_statements)
        else:
            self._exit_statements = None  # It will be generated when self.exit_statements is called
        # The default exit
        if lift_r.is_default_exit_constant == 1:
            self.default_exit_target = lift_r.default_exit
        else:
            self.default_exit_target = None

        # Data references
        self.data_refs = None
        if lift_r.data_ref_count > 0:
            if lift_r.data_ref_count > self.MAX_DATA_REFS:
                raise SkipStatementsError(f"data_ref_count exceeded MAX_DATA_REFS ({self.MAX_DATA_REFS})")
            self.data_refs = [DataRef.from_c(lift_r.data_refs[i]) for i in range(lift_r.data_ref_count)]

        # Const values
        self.const_vals = None
        if lift_r.const_val_count > 0:
            if lift_r.const_val_count > self.MAX_CONST_VALS:
                raise SkipStatementsError(f"const_val_count exceeded MAX_CONST_VALS ({self.MAX_CONST_VALS})")
            self.const_vals = [ConstVal.from_c(lift_r.const_vals[i]) for i in range(lift_r.const_val_count)]

    def _set_attributes(
        self,
        statements=None,
        nxt=None,
        tyenv=None,
        jumpkind=None,
        direct_next=None,
        size=None,
        instructions=None,
        instruction_addresses=None,
        exit_statements=None,
        default_exit_target=None,
    ):
        self.statements = statements if statements is not None else []
        self.next = nxt
        if tyenv is not None:
            self.tyenv = tyenv
        self.jumpkind = jumpkind
        self._direct_next = direct_next
        self._size = size
        self._instructions = instructions
        self._instruction_addresses = instruction_addresses
        self._exit_statements = exit_statements
        self.default_exit_target = default_exit_target

    def _from_py(self, irsb):
        self._set_attributes(
            irsb.statements,
            irsb.next,
            irsb.tyenv,
            irsb.jumpkind,
            irsb.direct_next,
            irsb.size,
            instructions=irsb._instructions,
            instruction_addresses=irsb._instruction_addresses,
            exit_statements=irsb.exit_statements,
            default_exit_target=irsb.default_exit_target,
        )


class IRTypeEnv(VEXObject):
    """
    An IR type environment.

    :ivar types:        A list of the types of all the temporaries in this block as VEX enum strings.
                        `types[3]` is the type of t3.
    :vartype types:     list of str
    """

    __slots__ = ["types", "wordty"]

    def __init__(self, arch, types=None):
        VEXObject.__init__(self)
        self.types = [] if types is None else types
        self.wordty = "Ity_I%d" % arch.bits

    def __str__(self):
        return " ".join(("t%d:%s" % (i, t)) for i, t in enumerate(self.types))

    def lookup(self, tmp: int) -> str:
        """
        Return the type of temporary variable `tmp` as an enum string
        """
        if tmp < 0 or tmp > self.types_used:
            log.debug("Invalid temporary number %d", tmp)
            raise IndexError(tmp)
        return self.types[tmp]

    def sizeof(self, tmp):
        return get_type_size(self.lookup(tmp))

    def add(self, ty):
        """
        Add a new tmp of type `ty` to the environment. Returns the number of the new tmp.
        """
        self.types.append(ty)
        return self.types_used - 1

    @property
    def types_used(self):
        return len(self.types)

    @staticmethod
    def _from_c(arch, c_tyenv):
        return IRTypeEnv(arch, [get_enum_from_int(c_tyenv.types[t]) for t in range(c_tyenv.types_used)])

    @staticmethod
    def _to_c(tyenv):
        c_tyenv = pvc.emptyIRTypeEnv()
        for ty in tyenv.types:
            pvc.newIRTemp(c_tyenv, get_int_from_enum(ty))
        return c_tyenv

    def typecheck(self):
        for ty in self.types:
            try:
                get_type_size(ty)
            except ValueError:
                return False
        return True


================================================
FILE: pyvex/const.py
================================================
# pylint:disable=missing-class-docstring,raise-missing-from,not-callable
import re
from abc import ABC

from .enums import VEXObject, get_enum_from_int
from .errors import PyVEXError
from .native import ffi, pvc


# IRConst hierarchy
class IRConst(VEXObject, ABC):
    __slots__ = ["_value"]

    type: str
    size: int
    tag: str
    c_constructor = None
    _value: int

    def pp(self):
        print(str(self))

    @property
    def value(self) -> int:
        return self._value

    @staticmethod
    def _from_c(c_const):
        if c_const[0] == ffi.NULL:
            return None

        tag = get_enum_from_int(c_const.tag)

        try:
            return tag_to_const_class(tag)._from_c(c_const)
        except KeyError:
            raise PyVEXError("Unknown/unsupported IRConstTag %s\n" % tag)

    _translate = _from_c

    @classmethod
    def _to_c(cls, const):
        # libvex throws an exception when constructing a U1 with a value other than 0 or 1
        if const.tag == "Ico_U1" and const.value not in (0, 1):
            raise PyVEXError("Invalid U1 value: %d" % const.value)

        try:
            return cls.c_constructor(const.value)
        except KeyError:
            raise PyVEXError("Unknown/unsupported IRConstTag %s]n" % const.tag)

    def __eq__(self, other):
        if not isinstance(other, type(self)):
            return False
        return self._value == other._value

    def __hash__(self):
        return hash((type(self), self._value))


class U1(IRConst):
    __slots__: list[str] = []

    type = "Ity_I1"
    size = 1
    tag = "Ico_U1"
    op_format = "1"
    c_constructor = pvc.IRConst_U1

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%d" % self.value

    @staticmethod
    def _from_c(c_const):
        return U1(c_const.Ico.U1)


class U8(IRConst):
    __slots__: list[str] = []

    type = "Ity_I8"
    size = 8
    tag = "Ico_U8"
    op_format = "8"
    c_constructor = pvc.IRConst_U8

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "0x%02x" % self.value

    @staticmethod
    def _from_c(c_const):
        return _U8_POOL[c_const.Ico.U8]


_U8_POOL = [U8(i) for i in range(256)]


class U16(IRConst):
    __slots__: list[str] = []

    type = "Ity_I16"
    size = 16
    tag = "Ico_U16"
    op_format = "16"
    c_constructor = pvc.IRConst_U16

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "0x%04x" % self.value

    @staticmethod
    def _from_c(c_const):
        val = c_const.Ico.U16
        if val < 1024:
            return _U16_POOL[val]
        if val >= 0xFC00:
            return _U16_POOL[val - 0xFC00 + 1024]
        return U16(val)


_U16_POOL = [U16(i) for i in range(1024)] + [U16(i) for i in range(0xFC00, 0xFFFF + 1)]


class U32(IRConst):
    __slots__: list[str] = []

    type = "Ity_I32"
    size = 32
    tag = "Ico_U32"
    op_format = "32"
    c_constructor = pvc.IRConst_U32

    def __init__(self, value: int):
        self._value = value

    def __str__(self):
        return "0x%08x" % self.value

    @staticmethod
    def _from_c(c_const):
        val = c_const.Ico.U32
        if val < 1024:
            return _U32_POOL[val]
        if val >= 0xFFFFFC00:
            return _U32_POOL[val - 0xFFFFFC00 + 1024]
        return U32(val)


_U32_POOL = [U32(i) for i in range(1024)] + [U32(i) for i in range(0xFFFFFC00, 0xFFFFFFFF + 1)]


class U64(IRConst):
    __slots__: list[str] = []

    type = "Ity_I64"
    size = 64
    tag = "Ico_U64"
    op_format = "64"
    c_constructor = pvc.IRConst_U64

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "0x%016x" % self.value

    @staticmethod
    def _from_c(c_const):
        val = c_const.Ico.U64
        if val < 1024:
            return _U64_POOL[val]
        if val >= 0xFFFFFFFFFFFFFC00:
            return _U64_POOL[val - 0xFFFFFFFFFFFFFC00 + 1024]
        return U64(val)


_U64_POOL = [U64(i) for i in range(1024)] + [U64(i) for i in range(0xFFFFFFFFFFFFFC00, 0xFFFFFFFFFFFFFFFF + 1)]

# Integer Type Imagination
class_cache = {1: U1, 8: U8, 16: U16, 32: U32, 64: U64}


def vex_int_class(size):
    try:
        return class_cache[size]
    except KeyError:

        class VexInt(IRConst):
            type = "Ity_I%d" % size
            tag = "Ico_U%d" % size
            op_format = str(size)

            def __init__(self, value):
                IRConst.__init__(self)
                self._value = value

            def __str__(self):
                return f"(0x{self.value:x} :: {self.type})"

        VexInt.__name__ = "U%d" % size
        class_cache[size] = VexInt
        return VexInt


class F32(IRConst):
    __slots__: list[str] = []

    type = "Ity_F32"
    tag = "Ico_F32"
    op_format = "F32"
    c_constructor = pvc.IRConst_F32
    size = 32

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%f" % self.value

    @staticmethod
    def _from_c(c_const):
        return F32(c_const.Ico.F32)


class F32i(IRConst):
    __slots__: list[str] = []

    type = "Ity_F32"
    tag = "Ico_F32i"
    op_format = "F32"
    c_constructor = pvc.IRConst_F32i
    size = 32

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%f" % self.value

    @staticmethod
    def _from_c(c_const):
        return F32i(c_const.Ico.F32)


class F64(IRConst):
    __slots__: list[str] = []

    type = "Ity_F64"
    tag = "Ico_F64"
    op_format = "F64"
    c_constructor = pvc.IRConst_F64
    size = 64

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%f" % self.value

    @staticmethod
    def _from_c(c_const):
        return F64(c_const.Ico.F64)


class F64i(IRConst):
    __slots__: list[str] = []

    type = "Ity_F64"
    tag = "Ico_F64i"
    op_format = "F64"
    c_constructor = pvc.IRConst_F64i
    size = 64

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%f" % self.value

    @staticmethod
    def _from_c(c_const):
        return F64i(c_const.Ico.F64)


class V128(IRConst):
    __slots__: list[str] = []

    type = "Ity_V128"
    tag = "Ico_V128"
    op_format = "V128"
    c_constructor = pvc.IRConst_V128
    size = 128

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%x" % self.value

    # vex doesn't store a full 128 bit constant, instead it stores 1 bit per 8 bits of data
    # and duplicates each bit 8 times
    @staticmethod
    def _from_c(c_const):
        base_const = c_const.Ico.V128
        real_const = 0
        for i in range(16):
            if (base_const >> i) & 1 == 1:
                real_const |= 0xFF << (8 * i)
        return V128(real_const)


class V256(IRConst):
    __slots__: list[str] = []

    type = "Ity_V256"
    tag = "Ico_V256"
    op_format = "V256"
    c_constructor = pvc.IRConst_V256
    size = 256

    def __init__(self, value):
        self._value = value

    def __str__(self):
        return "%x" % self.value

    # see above
    @staticmethod
    def _from_c(c_const):
        base_const = c_const.Ico.V256
        real_const = 0
        for i in range(32):
            if (base_const >> i) & 1 == 1:
                real_const |= 0xFF << (8 * i)
        return V256(real_const)


predefined_types = [U1, U8, U16, U32, U64, F32, F32i, F64, F64i, V128, V256]
predefined_types_map = {c.type: c for c in predefined_types}
predefined_classes_map = {c.tag: c for c in predefined_types}

# precompiled regexes
int_ty_re = re.compile(r"Ity_I\d+")
int_tag_re = re.compile(r"Ico_U\d+")
tag_size_re = re.compile(r"Ico_[UFV](?P<size>\d+)i?")


def is_int_ty(ty):
    m = int_ty_re.match(ty)
    return m is not None


def is_int_tag(tag):
    m = int_tag_re.match(tag)
    return m is not None


def get_tag_size(tag):
    m = tag_size_re.match(tag)
    if m is None:
        raise ValueError("Tag %s does not have size" % tag)
    return int(m.group("size"))


type_str_re = re.compile(r"Ity_[IFDV](?P<size>\d+)")
type_tag_str_re = re.compile(r"[IFDV]?(?P<size>\d+)[SU]?")


def get_type_size(ty):
    """
    Returns the size, in BITS, of a VEX type specifier
    e.g., Ity_I16 -> 16

    :param ty:
    :return:
    """
    m = type_str_re.match(ty)
    if m is None:
        raise ValueError("Type %s does not have size" % ty)
    return int(m.group("size"))


def get_type_spec_size(ty):
    """
    Get the width of a "type specifier"
    like I16U
    or F16
    or just 16
    (Yes, this really just takes the int out.  If we must special-case, do it here.
    :param tyspec:
    :return:
    """
    m = type_tag_str_re.match(ty)
    if m is None:
        raise ValueError("Type specifier %s does not have size" % ty)
    return int(m.group("size"))


def ty_to_const_class(ty):
    try:
        return predefined_types_map[ty]
    except KeyError:
        if is_int_ty(ty):
            size = get_type_size(ty)
            return vex_int_class(size)
        else:
            raise ValueError("Type %s does not exist" % ty)


def tag_to_const_class(tag):
    try:
        return predefined_classes_map[tag]
    except KeyError:
        if is_int_tag(tag):
            size = get_tag_size(tag)
            return vex_int_class(size)
        else:
            raise ValueError("Tag %s does not exist" % tag)


================================================
FILE: pyvex/const_val.py
================================================
class ConstVal:
    """
    A constant value object. Indicates a constant value assignment to a VEX tmp variable.

    :ivar tmp:          The tmp variable being assigned to.
    :ivar value:        The value of the tmp variable.
    :ivar stmt_idx:     The IRSB statement index containing the data access
    """

    __slots__ = (
        "tmp",
        "value",
        "stmt_idx",
    )

    def __init__(self, tmp: int, value: int, stmt_idx: int):
        self.tmp = tmp
        self.value = value
        self.stmt_idx = stmt_idx

    def __repr__(self):
        return f"<ConstVal {self.tmp} = {self.value:#x} @ {self.stmt_idx}>"

    @classmethod
    def from_c(cls, r):
        return cls(r.tmp, r.value, r.stmt_idx)


================================================
FILE: pyvex/data_ref.py
================================================
def data_ref_type_str(dref_enum):
    """
    Translate an ``enum DataRefTypes`` value into a string representation.
    """
    if dref_enum == 0x9000:
        return "unknown"
    elif dref_enum == 0x9001:
        return "integer"
    elif dref_enum == 0x9002:
        return "fp"
    elif dref_enum == 0x9003:
        return "integer(store)"
    else:
        return "INVALID"


class DataRef:
    """
    A data reference object. Indicates a data access in an IRSB.

    :ivar data_addr:    The address of the data being accessed
    :ivar data_size:    The size of the data being accessed, in bytes
    :ivar data_type:    The type of the data, a DataRefTypes enum.
    :ivar stmt_idx:     The IRSB statement index containing the data access
    :ivar ins_addr:     The address of the instruction performing the data access
    """

    __slots__ = ("data_addr", "data_size", "data_type", "stmt_idx", "ins_addr")

    def __init__(self, data_addr, data_size, data_type, stmt_idx, ins_addr):
        self.data_addr = data_addr
        self.data_size = data_size
        self.data_type = data_type
        self.stmt_idx = stmt_idx
        self.ins_addr = ins_addr

    @property
    def data_type_str(self):
        """
        The data ref type as a string, "unknown" "integer" "fp" or "INVALID"
        """
        return data_ref_type_str(self.data_type)

    def __repr__(self):
        return "<DataRef accessing %#x %s:%d at %#x:%d>" % (
            self.data_addr,
            data_ref_type_str(self.data_type),
            self.data_size,
            self.ins_addr,
            self.stmt_idx,
        )

    @classmethod
    def from_c(cls, r):
        return cls(r.data_addr, r.size, r.data_type, r.stmt_idx, r.ins_addr)


================================================
FILE: pyvex/enums.py
================================================
from typing import Any

from .native import ffi, pvc
from .utils import stable_hash


class VEXObject:
    """
    The base class for Vex types.
    """

    __slots__: list[str] = []

    def __eq__(self, other):
        if not isinstance(other, type(self)):
            return False
        # compare values in slots
        for slot in self.__slots__:
            if getattr(self, slot) != getattr(other, slot):
                return False
        return True

    def __hash__(self):
        values = [getattr(self, slot) for slot in self.__slots__]
        for i, lst_val in enumerate(values):
            if isinstance(lst_val, list):
                values[i] = tuple(lst_val)
        return stable_hash(tuple([type(self)] + values))


class IRCallee(VEXObject):
    """
    Describes a helper function to call.
    """

    __slots__ = ["regparms", "name", "mcx_mask"]

    def __init__(self, regparms, name, mcx_mask):
        VEXObject.__init__(self)
        self.regparms = regparms
        self.name = name
        self.mcx_mask = mcx_mask

    def __str__(self):
        return str(self.name)

    @staticmethod
    def _from_c(c_callee):
        return IRCallee(
            c_callee.regparms,
            ffi.string(c_callee.name).decode(),
            # NO. #int(ffi.cast("unsigned long long", c_callee.addr)),
            c_callee.mcx_mask,
        )

    @staticmethod
    def _to_c(callee):  # pylint: disable=unused-argument
        raise TypeError(
            "This doesn't work! Please invent a way to get the correct address for the named function from pyvex_c."
        )
        # c_callee = pvc.mkIRCallee(callee.regparms,
        #                          callee.name.encode(),
        #                          ffi.cast("void *", callee.addr))
        # c_callee.mcx_mask = callee.mcx_mask
        # return c_callee


class IRRegArray(VEXObject):
    """
    A section of the guest state that we want te be able to index at run time, so as to be able to describe indexed or
    rotating register files on the guest.

    :ivar int base:     The offset into the state that this array starts
    :ivar str elemTy:   The types of the elements in this array, as VEX enum strings
    :ivar int nElems:   The number of elements in this array
    """

    __slots__ = ["base", "elemTy", "nElems"]

    def __init__(self, base, elemTy, nElems):
        VEXObject.__init__(self)
        self.base = base
        self.elemTy = elemTy
        self.nElems = nElems

    def __str__(self):
        return "%s:%sx%d" % (self.base, self.elemTy[4:], self.nElems)

    @staticmethod
    def _from_c(c_arr):
        return IRRegArray(c_arr.base, ints_to_enums[c_arr.elemTy], c_arr.nElems)

    @staticmethod
    def _to_c(arr):
        return pvc.mkIRRegArray(arr.base, get_int_from_enum(arr.elemTy), arr.nElems)


ints_to_enums: dict[int, str] = {}
enums_to_ints: dict[str, int] = {}
irop_enums_to_ints: dict[str, int] = {}
will_be_overwritten = ["Ircr_GT", "Ircr_LT"]


def get_enum_from_int(i):
    return ints_to_enums[i]


def get_int_from_enum(e):
    return enums_to_ints[e]


_add_enum_counter = 0


def _add_enum(s, i=None):  # TODO get rid of this
    global _add_enum_counter  # pylint: disable=global-statement
    if i is None:
        while _add_enum_counter in ints_to_enums:
            _add_enum_counter += 1
        i = _add_enum_counter
        _add_enum_counter += 1  # Update for the next iteration
    if i in ints_to_enums:
        if ints_to_enums[i] not in will_be_overwritten:
            raise ValueError("Enum with intkey %d already present" % i)
    enums_to_ints[s] = i
    ints_to_enums[i] = s
    if s.startswith("Iop_"):
        irop_enums_to_ints[s] = i


for attr in dir(pvc):
    if attr[0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and hasattr(pvc, attr) and isinstance(getattr(pvc, attr), int):
        _add_enum(attr, getattr(pvc, attr))


def vex_endness_from_string(endness_str):
    return getattr(pvc, endness_str)


def default_vex_archinfo() -> dict[str, Any]:
    return {
        "hwcaps": 0,
        "endness": vex_endness_from_string("VexEndnessLE"),
        "ppc_icache_line_szB": 0,
        "ppc_dcbz_szB": 0,
        "ppc_dcbzl_szB": 0,
        "arm64_dMinLine_lg2_szB": 0,
        "arm64_iMinLine_lg2_szB": 0,
        "hwcache_info": {
            "num_levels": 0,
            "num_caches": 0,
            "caches": None,
            "icaches_maintain_coherence": True,
        },
        "x86_cr0": 0xFFFFFFFF,
    }


================================================
FILE: pyvex/errors.py
================================================
class PyVEXError(Exception):
    pass


class SkipStatementsError(PyVEXError):
    pass


#
# Exceptions and notifications that post-processors can raise
#


class LiftingException(Exception):
    pass


class NeedStatementsNotification(LiftingException):
    """
    A post-processor may raise a NeedStatementsNotification if it needs to work with statements, but the current IRSB
    is generated without any statement available (skip_stmts=True). The lifter will re-lift the current block with
    skip_stmts=False upon catching a NeedStatementsNotification, and re-run the post-processors.

    It's worth noting that if a post-processor always raises this notification for every basic block without statements,
    it will essentially disable the skipping statement optimization, and it is bad for performance (especially for
    CFGFast, which heavily relies on this optimization). Post-processor authors are encouraged to at least filter the
    IRSBs based on available properties (jumpkind, next, etc.). If a post-processor must work with statements for the
    majority of IRSBs, the author should implement it in PyVEX in C for the sake of a better performance.
    """

    pass


================================================
FILE: pyvex/expr.py
================================================
from __future__ import annotations

import logging
import re
from typing import TYPE_CHECKING

from .const import U8, U16, U32, U64, IRConst, get_type_size
from .enums import IRCallee, IRRegArray, VEXObject, get_enum_from_int, get_int_from_enum
from .errors import PyVEXError
from .native import ffi, pvc

if TYPE_CHECKING:
    from .block import IRTypeEnv

log = logging.getLogger("pyvex.expr")


class IRExpr(VEXObject):
    """
    IR expressions in VEX represent operations without side effects.
    """

    __slots__ = []

    tag: str | None = None
    tag_int = 0  # set automatically at bottom of file

    def pp(self):
        print(str(self))

    def __str__(self):
        return self._pp_str()

    def _pp_str(self) -> str:
        raise NotImplementedError

    @property
    def child_expressions(self) -> list[IRExpr]:
        """
        A list of all of the expressions that this expression ends up evaluating.
        """
        expressions = []
        for k in self.__slots__:
            v = getattr(self, k)
            if isinstance(v, IRExpr):
                expressions.append(v)
                expressions.extend(v.child_expressions)
        return expressions

    @property
    def constants(self):
        """
        A list of all of the constants that this expression ends up using.
        """
        constants = []
        for k in self.__slots__:
            v = getattr(self, k)
            if isinstance(v, IRExpr):
                constants.extend(v.constants)
            elif isinstance(v, IRConst):
                constants.append(v)
        return constants

    def result_size(self, tyenv: IRTypeEnv):
        return get_type_size(self.result_type(tyenv))

    def result_type(self, tyenv: IRTypeEnv):
        raise NotImplementedError()

    def replace_expression(self, replacements):
        """
        Replace child expressions in-place.

        :param Dict[IRExpr, IRExpr] replacements:  A mapping from expression-to-find to expression-to-replace-with
        :return:                    None
        """

        for k in self.__slots__:
            v = getattr(self, k)
            if isinstance(v, IRExpr) and v in replacements:
                setattr(self, k, replacements.get(v))
            elif isinstance(v, list):
                # Replace the instance in the list
                for i, expr_ in enumerate(v):
                    if isinstance(expr_, IRExpr) and expr_ in replacements:
                        v[i] = replacements.get(expr_)
            elif type(v) is tuple:
                # Rebuild the tuple
                _lst = []
                replaced = False
                for i, expr_ in enumerate(v):
                    if isinstance(expr_, IRExpr) and expr_ in replacements:
                        _lst.append(replacements.get(expr_))
                        replaced = True
                    else:
                        _lst.append(expr_)
                if replaced:
                    setattr(self, k, tuple(_lst))
            elif isinstance(v, IRExpr):
                v.replace_expression(replacements)

    @staticmethod
    def _from_c(c_expr) -> IRExpr | None:
        if c_expr == ffi.NULL or c_expr[0] == ffi.NULL:
            return None

        try:
            return enum_to_expr_class(c_expr.tag)._from_c(c_expr)
        except KeyError:
            raise PyVEXError("Unknown/unsupported IRExprTag %s\n" % get_enum_from_int(c_expr.tag))

    _translate = _from_c

    @staticmethod
    def _to_c(expr):
        try:
            return tag_to_expr_class(expr.tag)._to_c(expr)
        except KeyError:
            raise PyVEXError("Unknown/unsupported IRExprTag %s\n" % expr.tag)

    def typecheck(self, tyenv):
        return self.result_type(tyenv)


class Binder(IRExpr):
    """
    Used only in pattern matching within Vex. Should not be seen outside of Vex.
    """

    __slots__ = ["binder"]

    tag = "Iex_Binder"

    def __init__(self, binder):
        self.binder = binder

    def _pp_str(self):
        return "Binder"

    @staticmethod
    def _from_c(c_expr):
        return Binder(c_expr.iex.Binder.binder)

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Binder(expr.binder)

    def result_type(self, tyenv):
        return "Ity_INVALID"


class VECRET(IRExpr):
    tag = "Iex_VECRET"

    __slots__ = []

    def _pp_str(self):
        return "VECRET"

    @staticmethod
    def _from_c(c_expr):
        return VECRET()

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_VECRET()

    def result_type(self, tyenv):
        return "Ity_INVALID"


class GSPTR(IRExpr):
    __slots__ = []

    tag = "Iex_GSPTR"

    def _pp_str(self):
        return "GSPTR"

    @staticmethod
    def _from_c(c_expr):
        return GSPTR()

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_GSPTR()

    def result_type(self, tyenv):
        return "Ity_INVALID"


class GetI(IRExpr):
    """
    Read a guest register at a non-fixed offset in the guest state.
    """

    __slots__ = ["descr", "ix", "bias"]

    tag = "Iex_GetI"

    def __init__(self, descr, ix, bias):
        self.descr = descr
        self.ix = ix
        self.bias = bias

    @property
    def description(self):
        return self.descr

    @property
    def index(self):
        return self.ix

    def _pp_str(self):
        return f"GetI({self.descr})[{self.ix},{self.bias}]"

    @staticmethod
    def _from_c(c_expr):
        descr = IRRegArray._from_c(c_expr.Iex.GetI.descr)
        ix = IRExpr._from_c(c_expr.Iex.GetI.ix)
        bias = c_expr.Iex.GetI.bias
        return GetI(descr, ix, bias)

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_GetI(IRRegArray._to_c(expr.descr), IRExpr._to_c(expr.ix), expr.bias)

    def result_type(self, tyenv):
        return self.descr.elemTy


class RdTmp(IRExpr):
    """
    Read the value held by a temporary.
    """

    __slots__ = ["_tmp"]

    tag = "Iex_RdTmp"

    def __init__(self, tmp):
        self._tmp = tmp

    def _pp_str(self):
        return "t%d" % self.tmp

    @property
    def tmp(self):
        return self._tmp

    @staticmethod
    def _from_c(c_expr):
        tmp = c_expr.Iex.RdTmp.tmp
        return RdTmp.get_instance(tmp)

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_RdTmp(expr.tmp)

    @staticmethod
    def get_instance(tmp):
        if tmp < 1024:
            # for small tmp reads, they are cached and are only created once globally
            return _RDTMP_POOL[tmp]
        return RdTmp(tmp)

    def replace_expression(self, replacements):
        # RdTmp is one of the terminal IRExprs, which cannot be replaced.
        pass

    def result_type(self, tyenv):
        return tyenv.lookup(self.tmp)

    def __hash__(self):
        return 133700 + self._tmp


_RDTMP_POOL = list(RdTmp(i) for i in range(0, 1024))


class Get(IRExpr):
    """
    Read a guest register, at a fixed offset in the guest state.
    """

    __slots__ = ["offset", "ty_int"]

    tag = "Iex_Get"

    def __init__(self, offset: int, ty: str, ty_int: int | None = None):
        self.offset = offset
        if ty_int is None:
            self.ty_int = get_int_from_enum(ty)
        else:
            self.ty_int = ty_int

    @property
    def ty(self):
        return get_enum_from_int(self.ty_int)

    @property
    def type(self):
        return get_enum_from_int(self.ty_int)

    def _pp_str(self):
        return f"GET:{self.ty[4:]}(offset={self.offset})"

    def pp_str_with_name(self, reg_name: str):
        """pp_str_with_name is used to print the expression with the name of the
        register instead of the offset"""
        return f"GET:{self.ty[4:]}({reg_name})"

    @staticmethod
    def _from_c(c_expr):
        return Get(c_expr.Iex.Get.offset, get_enum_from_int(c_expr.Iex.Get.ty))

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Get(expr.offset, expr.ty_int)

    def result_type(self, tyenv):
        return self.ty

    def __hash__(self):
        return (self.offset << 8) | self.ty_int


class Qop(IRExpr):
    """
    A quaternary operation (4 arguments).
    """

    __slots__ = ["op", "args"]

    tag = "Iex_Qop"

    def __init__(self, op, args):
        self.op = op
        self.args = args

    def _pp_str(self):
        return "{}({})".format(self.op[4:], ",".join(str(a) for a in self.args))

    @property
    def child_expressions(self):
        expressions = sum((a.child_expressions for a in self.args), [])
        expressions.extend(self.args)
        return expressions

    @staticmethod
    def _from_c(c_expr):
        return Qop(
            get_enum_from_int(c_expr.Iex.Qop.details.op),
            [
                IRExpr._from_c(arg)
                for arg in [
                    c_expr.Iex.Qop.details.arg1,
                    c_expr.Iex.Qop.details.arg2,
                    c_expr.Iex.Qop.details.arg3,
                    c_expr.Iex.Qop.details.arg4,
                ]
            ],
        )

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Qop(get_int_from_enum(expr.op), *[IRExpr._to_c(arg) for arg in expr.args])

    def result_type(self, tyenv):
        return get_op_retty(self.op)

    def typecheck(self, tyenv):  # TODO change all this to use PyvexTypeErrorException
        resty, (arg1ty, arg2ty, arg3ty, arg4ty) = op_arg_types(self.op)
        arg1ty_real = self.args[0].typecheck(tyenv)
        arg2ty_real = self.args[1].typecheck(tyenv)
        arg3ty_real = self.args[2].typecheck(tyenv)
        arg4ty_real = self.args[3].typecheck(tyenv)
        if arg1ty_real is None or arg2ty_real is None or arg3ty_real is None or arg4ty_real is None:
            return None

        if arg1ty_real != arg1ty:
            log.debug("First arg of %s must be %s", self.op, arg1ty)
            return None
        if arg2ty_real != arg2ty:
            log.debug("Second arg of %s must be %s", self.op, arg2ty)
            return None
        if arg3ty_real != arg3ty:
            log.debug("Third arg of %s must be %s", self.op, arg3ty)
            return None
        if arg4ty_real != arg4ty:
            log.debug("Fourth arg of %s must be %s", self.op, arg4ty)
            return None

        return resty


class Triop(IRExpr):
    """
    A ternary operation (3 arguments)
    """

    __slots__ = ["op", "args"]

    tag = "Iex_Triop"

    def __init__(self, op, args):
        self.op = op
        self.args = args

    def _pp_str(self):
        return "{}({})".format(self.op[4:], ",".join(str(a) for a in self.args))

    @property
    def child_expressions(self):
        expressions = sum((a.child_expressions for a in self.args), [])
        expressions.extend(self.args)
        return expressions

    @staticmethod
    def _from_c(c_expr):
        return Triop(
            get_enum_from_int(c_expr.Iex.Triop.details.op),
            [
                IRExpr._from_c(arg)
                for arg in [c_expr.Iex.Triop.details.arg1, c_expr.Iex.Triop.details.arg2, c_expr.Iex.Triop.details.arg3]
            ],
        )

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Triop(get_int_from_enum(expr.op), *[IRExpr._to_c(arg) for arg in expr.args])

    def result_type(self, tyenv):
        return get_op_retty(self.op)

    def typecheck(self, tyenv):
        resty, (arg1ty, arg2ty, arg3ty) = op_arg_types(self.op)
        arg1ty_real = self.args[0].typecheck(tyenv)
        arg2ty_real = self.args[1].typecheck(tyenv)
        arg3ty_real = self.args[2].typecheck(tyenv)
        if arg1ty_real is None or arg2ty_real is None or arg3ty_real is None:
            return None

        if arg1ty_real != arg1ty:
            log.debug("First arg of %s must be %s", self.op, arg1ty)
            return None
        if arg2ty_real != arg2ty:
            log.debug("Second arg of %s must be %s", self.op, arg2ty)
            return None
        if arg3ty_real != arg3ty:
            log.debug("Third arg of %s must be %s", self.op, arg3ty)
            return None

        return resty


class Binop(IRExpr):
    """
    A binary operation (2 arguments).
    """

    __slots__ = ["_op", "op_int", "args"]

    tag = "Iex_Binop"

    def __init__(self, op, args, op_int=None):
        self.op_int = op_int
        self.args = args
        self._op = op if op is not None else None

    def _pp_str(self):
        return "{}({})".format(self.op[4:], ",".join(str(a) for a in self.args))

    @property
    def op(self):
        if self._op is None:
            self._op = get_enum_from_int(self.op_int)
        return self._op

    @property
    def child_expressions(self):
        expressions = sum((a.child_expressions for a in self.args), [])
        expressions.extend(self.args)
        return expressions

    @staticmethod
    def _from_c(c_expr):
        return Binop(
            None,
            [IRExpr._from_c(arg) for arg in [c_expr.Iex.Binop.arg1, c_expr.Iex.Binop.arg2]],
            op_int=c_expr.Iex.Binop.op,
        )

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Binop(get_int_from_enum(expr.op), *[IRExpr._to_c(arg) for arg in expr.args])

    def result_type(self, tyenv):
        return get_op_retty(self.op)

    def typecheck(self, tyenv):
        arg1ty_real = self.args[0].typecheck(tyenv)
        arg2ty_real = self.args[1].typecheck(tyenv)

        resty, (arg1ty, arg2ty) = op_arg_types(self.op)
        if arg1ty_real is None or arg2ty_real is None:
            return None

        if arg1ty_real != arg1ty:
            log.debug("First arg of %s must be %s", self.op, arg1ty)
            return None
        if arg2ty_real != arg2ty:
            log.debug("Second arg of %s must be %s", self.op, arg2ty)
            return None

        return resty


class Unop(IRExpr):
    """
    A unary operation (1 argument).
    """

    __slots__ = ["op", "args"]

    tag = "Iex_Unop"

    def __init__(self, op: str, args: list[IRExpr]):
        self.op = op
        self.args = args

    def _pp_str(self):
        return "{}({})".format(self.op[4:], ",".join(str(a) for a in self.args))

    @property
    def child_expressions(self):
        expressions = sum((a.child_expressions for a in self.args), [])
        expressions.extend(self.args)
        return expressions

    @staticmethod
    def _from_c(c_expr):
        return Unop(get_enum_from_int(c_expr.Iex.Unop.op), [IRExpr._from_c(c_expr.Iex.Unop.arg)])

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Unop(get_int_from_enum(expr.op), IRExpr._to_c(expr.args[0]))

    def result_type(self, tyenv):
        return get_op_retty(self.op)

    def typecheck(self, tyenv):
        resty, (arg1ty,) = op_arg_types(self.op)
        arg1ty_real = self.args[0].typecheck(tyenv)
        if arg1ty_real is None:
            return None

        if arg1ty_real != arg1ty:
            log.debug("First arg of %s must be %s", self.op, arg1ty)
            return None

        return resty


class Load(IRExpr):
    """
    A load from memory.
    """

    __slots__ = ["end", "ty", "addr"]

    tag = "Iex_Load"

    def __init__(self, end, ty, addr):
        self.end = end
        self.ty = ty
        self.addr = addr

    @property
    def endness(self):
        return self.end

    @property
    def type(self):
        return self.ty

    def _pp_str(self):
        return f"LD{self.end[-2:].lower()}:{self.ty[4:]}({self.addr})"

    @staticmethod
    def _from_c(c_expr):
        return Load(
            get_enum_from_int(c_expr.Iex.Load.end),
            get_enum_from_int(c_expr.Iex.Load.ty),
            IRExpr._from_c(c_expr.Iex.Load.addr),
        )

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Load(get_int_from_enum(expr.end), get_int_from_enum(expr.ty), IRExpr._to_c(expr.addr))

    def result_type(self, tyenv):
        return self.ty

    def typecheck(self, tyenv):
        addrty = self.addr.typecheck(tyenv)
        if addrty is None:
            return None
        if addrty != tyenv.wordty:
            log.debug("Address must be word-sized")
            return None
        return self.ty


class Const(IRExpr):
    """
    A constant expression.
    """

    __slots__ = ["_con"]

    tag = "Iex_Const"

    def __init__(self, con: IRConst):
        self._con = con

    def _pp_str(self):
        return str(self.con)

    @property
    def con(self) -> IRConst:
        return self._con

    @staticmethod
    def _from_c(c_expr):
        con = IRConst._from_c(c_expr.Iex.Const.con)
        return Const.get_instance(con)

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_Const(IRConst._to_c(expr.con))

    @staticmethod
    def get_instance(con):
        if con.value < 1024 and con.__class__ in _CONST_POOL:
            return _CONST_POOL[con.__class__][con.value]
        return Const(con)

    def result_type(self, tyenv):
        return self.con.type


_CONST_POOL = {
    U8: [Const(U8(i)) for i in range(0, 1024)],
    U16: [Const(U16(i)) for i in range(0, 1024)],
    U32: [Const(U32(i)) for i in range(0, 1024)],
    U64: [Const(U64(i)) for i in range(0, 1024)],
}


class ITE(IRExpr):
    """
    An if-then-else expression.
    """

    __slots__ = ["cond", "iffalse", "iftrue"]

    tag = "Iex_ITE"

    def __init__(self, cond, iffalse, iftrue):
        self.cond = cond
        self.iffalse = iffalse
        self.iftrue = iftrue

    def _pp_str(self):
        return f"ITE({self.cond},{self.iftrue},{self.iffalse})"

    @staticmethod
    def _from_c(c_expr):
        return ITE(
            IRExpr._from_c(c_expr.Iex.ITE.cond),
            IRExpr._from_c(c_expr.Iex.ITE.iffalse),
            IRExpr._from_c(c_expr.Iex.ITE.iftrue),
        )

    @staticmethod
    def _to_c(expr):
        return pvc.IRExpr_ITE(IRExpr._to_c(expr.cond), IRExpr._to_c(expr.iftrue), IRExpr._to_c(expr.iffalse))

    def result_type(self, tyenv):
        return self.iftrue.result_type(tyenv)

    def typecheck(self, tyenv):
        condty = self.cond.typecheck(tyenv)
        falsety = self.iffalse.typecheck(tyenv)
        truety = self.iftrue.typecheck(tyenv)

        if condty is None or falsety is None or truety is None:
            return None

        if condty != "Ity_I1":
            log.debug("guard must be Ity_I1")
            return None

        if falsety != truety:
            log.debug("false condition must be same type as true condition")
            return None

        return falsety


class CCall(IRExpr):
    """
    A call to a pure (no side-effects) helper C function.
    """

    __slots__ = ["retty", "cee", "args"]

    tag = "Iex_CCall"

    def __init__(self, retty, cee, args):
        self.retty = retty
        self.cee = cee
        self.args = tuple(args)

    @property
    def ret_type(self):
        return self.retty

    @property
    def callee(self):
        return self.cee

    def _pp_str(self):
        return "{}({}):{}".format(self.cee, ",".join(str(a) for a in self.args), self.retty)

    @property
    def child_expressions(self):
        expressions = sum((a.child_expressions for a in self.args), [])
        expressions.extend(self.args)
        return expressions

    @staticmethod
    def _from_c(c_expr):
        i = 0
        args = []
        while True:
            arg = c_expr.Iex.CCall.args[i]
            if arg == ffi.NULL:
                break
            args.append(IRExpr._from_c(arg))
            i += 1

        return CCall(get_enum_from_int(c_expr.Iex.CCall.retty), IRCallee._from_c(c_expr.Iex.CCall.cee), tuple(args))

    @staticmethod
    def _to_c(expr):
        args = [IRExpr._to_c(arg) for arg in expr.args]
        mkIRExprVec = getattr(pvc, "mkIRExprVec_%d" % len(args))
        return pvc.IRExpr_CCall(IRCallee._to_c(expr.cee), get_int_from_enum(expr.retty), mkIRExprVec(*args))

    def result_type(self, tyenv):
        return self.retty


def get_op_retty(op):
    return op_arg_types(op)[0]


op_signatures: dict[str, tuple[str, tuple[str, ...]]] = {}


def _request_op_type_from_cache(op):
    return op_signatures[op]


def _request_op_type_from_libvex(op):
    Ity_INVALID = 0x1100  # as defined in enum IRType in VEX

    res_ty = ffi.new("IRType *")
    arg_tys = [ffi.new("IRType *") for _ in range(4)]
    # initialize all IRTypes to Ity_INVALID
    for arg in arg_tys:
        arg[0] = Ity_INVALID
    pvc.typeOfPrimop(get_int_from_enum(op), res_ty, *arg_tys)
    arg_ty_vals = [a[0] for a in arg_tys]

    try:
        numargs = arg_ty_vals.index(Ity_INVALID)
    except ValueError:
        numargs = 4
    args_tys_list = [get_enum_from_int(arg_ty_vals[i]) for i in range(numargs)]

    op_ty_sig = (get_enum_from_int(res_ty[0]), tuple(args_tys_list))
    op_signatures[op] = op_ty_sig
    return op_ty_sig


class PyvexOpMatchException(Exception):
    pass


class PyvexTypeErrorException(Exception):
    pass


def int_type_for_size(size):
    return "Ity_I%d" % size


# precompiled regexes
unop_signature_re = re.compile(r"Iop_(Not|Ctz|Clz)(?P<size>\d+)$")
binop_signature_re = re.compile(r"Iop_(Add|Sub|Mul|Xor|Or|And|Div[SU]|Mod)(?P<size>\d+)$")
shift_signature_re = re.compile(r"Iop_(Shl|Shr|Sar)(?P<size>\d+)$")
cmp_signature_re_1 = re.compile(r"Iop_Cmp(EQ|NE)(?P<size>\d+)$")
cmp_signature_re_2 = re.compile(r"Iop_Cmp(GT|GE|LT|LE)(?P<size>\d+)[SU]$")
mull_signature_re = re.compile(r"Iop_Mull[SU](?P<size>\d+)$")
half_signature_re = re.compile(r"Iop_DivMod[SU](?P<fullsize>\d+)to(?P<halfsize>\d+)$")
cast_signature_re = re.compile(r"Iop_(?P<srcsize>\d+)(U|S|HI|HL)?to(?P<dstsize>\d+)")


def unop_signature(op):
    m = unop_signature_re.match(op)
    if m is None:
        raise PyvexOpMatchException()
    size = int(m.group("size"))
    size_type = int_type_for_size(size)
    return size_type, (size_type,)


def binop_signature(op):
    m = binop_signature_re.match(op)
    if m is None:
        raise PyvexOpMatchException()
    size = int(m.group("size"))
    size_type = int_type_for_size(size)
    return (size_type, (size_type, size_type))


def shift_signature(op):
    m = shift_signature_re.match(op)
    if m is None:
        raise PyvexOpMatchException()
    size = int(m.group("size"))
    if size > 255:
        raise PyvexTypeErrorException("Cannot apply shift operation to %d size int because shift index is 8-bit" % size)
    size_type = int_type_for_size(size)
    return (size_type, (size_type, int_type_for_size(8)))


def cmp_signature(op):
    m = cmp_signature_re_1.match(op)
    m2 = cmp_signature_re_2.match(op)
    if (m is None) == (m2 is None):
        raise PyvexOpMatchException()
    mfound = m if m is not None else m2
    assert mfound is not None
    size = int(mfound.group("size"))
    size_type = int_type_for_size(size)
    return (int_type_for_size(1), (size_type, size_type))


def mull_signature(op):
    m = mull_signature_re.match(op)
    if m is None:
        raise PyvexOpMatchException()
    size = int(m.group("size"))
    size_type = int_type_for_size(size)
    doubled_size_type = int_type_for_size(2 * size)
    return (doubled_size_type, (size_type, size_type))


def half_signature(op):
    m = half_signature_re.match(op)
    if m is None:
        raise PyvexOpMatchException()
    fullsize = int(m.group("fullsize"))
    halfsize = int(m.group("halfsize"))
    if halfsize * 2 != fullsize:
        raise PyvexTypeErrorException("Invalid Instruction %s: Type 1 must be twice the size of type 2" % op)
    fullsize_type = int_type_for_size(fullsize)
    halfsize_type = int_type_for_size(halfsize)
    return (fullsize_type, (fullsize_type, halfsize_type))


def cast_signature(op):
    m = cast_signature_re.match(op)
    if m is None:
        raise PyvexOpMatchException()
    src_type = int_type_for_size(int(m.group("srcsize")))
    dst_type = int_type_for_size(int(m.group("dstsize")))
    return (dst_type, (src_type,))


polymorphic_op_processors = [
    unop_signature,
    binop_signature,
    shift_signature,
    cmp_signature,
    mull_signature,
    half_signature,
    cast_signature,
]


def _request_polymorphic_op_type(op):
    for polymorphic_signature in polymorphic_op_processors:
        try:
            op_ty_sig = polymorphic_signature(op)
            break
        except PyvexOpMatchException:
            continue
    else:
        raise PyvexOpMatchException("Op %s not recognized" % op)
    return op_ty_sig


_request_funcs = [_request_op_type_from_cache, _request_op_type_from_libvex, _request_polymorphic_op_type]


def op_arg_types(op):
    for _request_func in _request_funcs:
        try:
            return _request_func(op)
        except KeyError:
            continue
    raise ValueError("Cannot find type of op %s" % op)


_globals = globals().copy()
#
# Mapping from tag strings/enums to IRExpr classes
#
tag_to_expr_mapping = {}
enum_to_expr_mapping = {}
tag_count = 0
cls = None
for cls in _globals.values():
    if type(cls) is type and issubclass(cls, IRExpr) and cls is not IRExpr:
        tag_to_expr_mapping[cls.tag] = cls
        enum_to_expr_mapping[get_int_from_enum(cls.tag)] = cls
        cls.tag_int = tag_count
        tag_count += 1
del cls


def tag_to_expr_class(tag):
    """
    Convert a tag string to the corresponding IRExpr class type.

    :param str tag: The tag string.
    :return:        A class.
    :rtype:         type
    """

    try:
        return tag_to_expr_mapping[tag]
    except KeyError:
        raise KeyError("Cannot find expression class for type %s." % tag)


def enum_to_expr_class(tag_enum):
    """
    Convert a tag enum to the corresponding IRExpr class.

    :param int tag_enum: The tag enum.
    :return:             A class.
    :rtype:              type
    """

    try:
        return enum_to_expr_mapping[tag_enum]
    except KeyError:
        raise KeyError("Cannot find expression class for type %s." % get_enum_from_int(tag_enum))


================================================
FILE: pyvex/lifting/__init__.py
================================================
from .gym import AARCH64Spotter, AMD64Spotter, ARMSpotter, X86Spotter
from .libvex import LIBVEX_SUPPORTED_ARCHES, LibVEXLifter
from .lift_function import lift, lifters, register
from .lifter import Lifter
from .post_processor import Postprocessor
from .zerodivision import ZeroDivisionPostProcessor

for arch in LIBVEX_SUPPORTED_ARCHES:
    register(LibVEXLifter, arch)
register(AARCH64Spotter, "AARCH64")
register(ARMSpotter, "ARM")
register(ARMSpotter, "ARMEL")
register(ARMSpotter, "ARMHF")
register(ARMSpotter, "ARMCortexM")
register(AMD64Spotter, "AMD64")
register(X86Spotter, "X86")

__all__ = ["Lifter", "Postprocessor", "lift", "register", "lifters", "ZeroDivisionPostProcessor"]


================================================
FILE: pyvex/lifting/gym/README.md
================================================
# The Gym

This is where we're putting non-libvex lifters that we feel should be included with the pyvex distribution.

These will probably be mostly "spotters", which correct for gaps in libvex's instruction support.




================================================
FILE: pyvex/lifting/gym/__init__.py
================================================
from .aarch64_spotter import AARCH64Spotter
from .arm_spotter import ARMSpotter
from .x86_spotter import AMD64Spotter, X86Spotter

__all__ = ("ARMSpotter", "AARCH64Spotter", "X86Spotter", "AMD64Spotter")


================================================
FILE: pyvex/lifting/gym/aarch64_spotter.py
================================================
import logging

from pyvex.lifting.util.instr_helper import Instruction
from pyvex.lifting.util.lifter_helper import GymratLifter

log = logging.getLogger(__name__)


class Aarch64Instruction(Instruction):  # pylint: disable=abstract-method
    # NOTE: WARNING: There is no MRS, MSR, SYSL in VEX's ARM implementation
    # You must use straight nasty hacks instead.
    pass


class Instruction_SYSL(Aarch64Instruction):
    name = "SYSL"
    bin_format = "1101010100101qqqnnnnmmmmppprrrrr"

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug("Ignoring SYSL instruction at %#x.", self.addr)


class Instruction_MSR(Aarch64Instruction):
    name = "MSR"
    bin_format = "11010101000ioqqqnnnnmmmmppprrrrr"

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug("Ignoring MSR instruction at %#x.", self.addr)


class Instruction_MRS(Aarch64Instruction):
    name = "MRS"
    bin_format = "110101010011opppnnnnmmmmppprrrrr"

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug("Ignoring MRS instruction at %#x.", self.addr)


class AARCH64Spotter(GymratLifter):
    instrs = [Instruction_MRS, Instruction_MSR, Instruction_SYSL]


================================================
FILE: pyvex/lifting/gym/arm_spotter.py
================================================
import logging

import bitstring

from pyvex.lifting.util import JumpKind, Type
from pyvex.lifting.util.instr_helper import Instruction, ParseError
from pyvex.lifting.util.lifter_helper import GymratLifter
from pyvex.types import Arch

log = logging.getLogger(__name__)


class ARMInstruction(Instruction):  # pylint: disable=abstract-method
    # NOTE: WARNING: There is no CPSR in VEX's ARM implementation
    # You must use straight nasty hacks instead.

    # NOTE 2: Something is goofy w/r/t archinfo and VEX; cc_op3 is used in ccalls, but there's
    # no cc_op3 in archinfo, angr itself uses cc_depn instead.  We do the same.

    def match_instruction(self, data, bitstrm):
        """
        ARM Instructions are pretty dense, so let's do what we can to weed them out
        """
        if "c" not in data or data["c"] == "1111":
            raise ParseError("Invalid ARM Instruction")

    def get_N(self):
        cc_op = self.get("cc_op", Type.int_32)
        cc_dep1 = self.get("cc_dep1", Type.int_32)
        cc_dep2 = self.get("cc_dep2", Type.int_32)
        cc_depn = self.get("cc_ndep", Type.int_32)
        return self.ccall(Type.int_32, "armg_calculate_flag_n", [cc_op, cc_dep1, cc_dep2, cc_depn])

    def get_C(self):
        cc_op = self.get("cc_op", Type.int_32)
        cc_dep1 = self.get("cc_dep1", Type.int_32)
        cc_dep2 = self.get("cc_dep2", Type.int_32)
        cc_depn = self.get("cc_ndep", Type.int_32)
        return self.ccall(Type.int_32, "armg_calculate_flag_c", [cc_op, cc_dep1, cc_dep2, cc_depn])

    def get_V(self):
        cc_op = self.get("cc_op", Type.int_32)
        cc_dep1 = self.get("cc_dep1", Type.int_32)
        cc_dep2 = self.get("cc_dep2", Type.int_32)
        cc_depn = self.get("cc_ndep", Type.int_32)
        return self.ccall(Type.int_32, "armg_calculate_flag_v", [cc_op, cc_dep1, cc_dep2, cc_depn])

    def get_Z(self):
        cc_op = self.get("cc_op", Type.int_32)
        cc_dep1 = self.get("cc_dep1", Type.int_32)
        cc_dep2 = self.get("cc_dep2", Type.int_32)
        cc_depn = self.get("cc_ndep", Type.int_32)
        return self.ccall(Type.int_32, "armg_calculate_flag_z", [cc_op.rdt, cc_dep1.rdt, cc_dep2.rdt, cc_depn.rdt])

    def evaluate_condition(self):
        # condition codes should be in 'c'
        cond = self.data["c"]
        if cond == "0000":
            # equal, z set
            return self.get_Z() == 1
        elif cond == "0001":
            # not equal, Z clear
            return self.get_Z() == 0
        elif cond == "0010":
            # Carry, C set
            return self.get_C() == 1
        elif cond == "0011":
            # Carry Clear, C clear
            return self.get_C() == 0
        elif cond == "0100":
            # MI / neagative / N set
            return self.get_N() == 1
        elif cond == "0101":
            # PL / plus / positive / N clear
            return self.get_N() == 0
        elif cond == "0110":
            # VS / V set / Overflow
            return self.get_V() == 1
        elif cond == "0111":
            # VC / V Clear / no overflow
            return self.get_V() == 0
        elif cond == "1000":
            # Hi / unsigned higher / C set, Z clear
            return (self.get_C() == 1) & (self.get_Z() == 0)
        elif cond == "1001":
            # LS / C clear, Z set
            return (self.get_C() == 0) & (self.get_Z() == 1)
        elif cond == "1011":
            # LT / Less than / N != V
            return self.get_N() != self.get_V()
        elif cond == "1100":
            # GT / greater than / Z clear and (n == v)
            return (self.get_Z() == 1) & (self.get_N() != self.get_V())
        elif cond == "1101":
            # LE / less than or equal to / Z set OR (N != V)
            return (self.get_Z() == 1) | (self.get_N() != self.get_V())
        else:
            # No condition
            return None

    def _load_le_instr(self, bitstream: bitstring.ConstBitStream, numbits: int) -> str:
        # THUMB mode instructions swap endianness every two bytes!
        if (self.addr & 1) == 1 and numbits > 16:
            chunk = ""
            oldpos = bitstream.pos
            try:
                for _ in range(0, numbits, 16):
                    chunk += bitstring.Bits(uint=bitstream.peek("uintle:%d" % 16), length=16).bin
                    bitstream.pos += 16
            finally:
                bitstream.pos = oldpos
            return chunk
        return super()._load_le_instr(bitstream, numbits)


class Instruction_MRC(ARMInstruction):
    name = "MRC"
    bin_format = "cccc1110CCC1nnnnddddppppOOOOOOOO"
    # 11101110000100010001111100010000
    # c = cond
    # C = Coprocessor operation mode
    # d = CPd
    # O = Offset
    # p = CP#

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO at least look at the conditionals
        # TODO Clobber the dst reg of MCR
        # TODO maybe treat coproc regs as simple storage (even though they are very much not)
        log.debug("Ignoring MRC instruction at %#x.", self.addr)


class Instruction_MCR(ARMInstruction):
    name = "MCR"
    bin_format = "cccc1110CCC0nnnnddddppppOOOOOOOO"
    # 11101110000000010000111100010000
    # c = cond
    # C = Coprocessor operation mode
    # d = CPd
    # O = Offset
    # p = CP#

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO at least look at the conditionals
        # TODO Clobber the dst reg of MCR
        # TODO maybe treat coproc regs as simple storage (even though they are very much not)
        log.debug("Ignoring MCR instruction at %#x.", self.addr)


class Instruction_MSR(ARMInstruction):
    name = "MSR"
    bin_format = "cccc00i10d10xxxj1111ssssssssssss"
    #             11100011001000011111000010010001
    #             11100001011011111111000000000001

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug(
            "Ignoring MSR instruction at %#x. VEX cannot support this instruction. "
            "See pyvex/lifting/gym/arm_spotter.py",
            self.addr,
        )


class Instruction_MRS(ARMInstruction):
    name = "MRS"
    bin_format = "cccc00010s001111dddd000000000000"

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug(
            "Ignoring MRS instruction at %#x. VEX cannot support this instruction. "
            "See pyvex/lifting/gym/arm_spotter.py",
            self.addr,
        )


class Instruction_STM(ARMInstruction):
    name = "STM"
    bin_format = "cccc100pu1w0bbbbrrrrrrrrrrrrrrrr"

    def match_instruction(self, data, bitstrm):
        # If we don't push anything, that's not real
        if int(data["r"]) == 0:
            raise ParseError("Invalid STM instruction")
        return True

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug(
            "Ignoring STMxx ^ instruction at %#x. This mode is not implemented by VEX! "
            "See pyvex/lifting/gym/arm_spotter.py",
            self.addr,
        )


class Instruction_LDM(ARMInstruction):
    name = "LDM"
    bin_format = "cccc100PU1W1bbbbrrrrrrrrrrrrrrrr"

    def match_instruction(self, data, bitstrm):
        # If we don't push anything, that's not real
        if int(data["r"]) == 0:
            raise ParseError("Invalid LDM instruction")
        return True

    def compute_result(self):  # pylint: disable=arguments-differ
        # test if PC will be set. If so, the jumpkind of this block should be Ijk_Ret
        log.debug("Spotting an LDM instruction at %#x.  This is not fully tested.  Prepare for errors.", self.addr)

        src_n = f"r{int(self.data['b'], 2)}"
        src = self.get(src_n, Type.int_32)

        for reg_num, bit in enumerate(self.data["r"]):
            reg_num = 15 - reg_num
            if bit == "1":
                if self.data["P"] == "1":
                    if self.data["U"] == "0":
                        src += 4
                    else:
                        src -= 4
                val = self.load(src, Type.int_32)
                self.put(val, f"r{reg_num}")
                if self.data["P"] == "0":
                    if self.data["U"] == "0":
                        src += 4
                    else:
                        src -= 4
                # If we touch PC, we're doing a RET!
                if reg_num == 15 and bit == "1":
                    cond = self.evaluate_condition()
                    if cond is not None:
                        self.jump(cond, val, JumpKind.Ret)
                    else:
                        self.jump(None, val, JumpKind.Ret)
        # Write-back
        if self.data["W"] == "1":
            self.put(src, src_n)


class Instruction_STC(ARMInstruction):
    name = "STC"
    bin_format = "cccc110PUNW0nnnnddddppppOOOOOOOO"

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO At least look at the conditionals
        log.debug("Ignoring STC instruction at %#x.", self.addr)


class Instruction_STC_THUMB(ARMInstruction):
    name = "STC"
    bin_format = "111c110PUNW0nnnnddddppppOOOOOOOO"

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO At least look at the conditionals
        log.debug("Ignoring STC instruction at %#x.", self.addr)


class Instruction_LDC(ARMInstruction):
    name = "LDC"
    bin_format = "cccc110PUNW1nnnnddddppppOOOOOOOO"

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO At least look at the conditionals
        # TODO Clobber the dest reg of LDC
        # TODO Maybe clobber the dst reg of CDP, if we're really adventurous
        log.debug("Ignoring LDC instruction at %#x.", self.addr)


class Instruction_LDC_THUMB(ARMInstruction):
    name = "LDC"
    bin_format = "111c110PUNW1nnnnddddppppOOOOOOOO"

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO At least look at the conditionals
        # TODO Clobber the dest reg of LDC
        # TODO Maybe clobber the dst reg of CDP, if we're really adventurous
        log.debug("Ignoring LDC instruction at %#x.", self.addr)


class Instruction_CDP(Instruction):
    name = "CDP"
    bin_format = "cccc1110oooonnnnddddppppPPP0mmmm"
    # c = cond
    # d = CPd
    # O = Offset
    # p = CP#

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO At least look at the conditionals
        # TODO Maybe clobber the dst reg of CDP, if we're really adventurous
        log.debug("Ignoring CDP instruction at %#x.", self.addr)


##
## Thumb! (ugh)
##


class ThumbInstruction(Instruction):  # pylint: disable=abstract-method
    def mark_instruction_start(self):
        self.irsb_c.imark(self.addr - 1, self.bytewidth, 1)


class Instruction_tCPSID(ThumbInstruction):
    name = "CPSID"
    bin_format = "101101x0011x0010"

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO haha lol yeah right
        log.debug("[thumb] Ignoring CPS instruction at %#x.", self.addr)


class Instruction_tMSR(ThumbInstruction):
    name = "tMSR"
    bin_format = "10x0mmmmxxxxxxxx11110011100Rrrrr"

    def compute_result(self):  # pylint: disable=arguments-differ
        dest_spec_reg = int(self.data["x"], 2)
        src_reg = f"r{int(self.data['r'], 2)}"

        # If 0, do not write the SPSR
        if self.data["R"] == "0":
            if dest_spec_reg == 8:  # msp
                src = self.get(src_reg, Type.int_32)
                self.put(src, "sp")
            elif dest_spec_reg == 16:  # primask
                src = self.get(src_reg, Type.int_32)
                self.put(src, "primask")
            else:
                log.debug(
                    "[thumb] FIXME: tMSR at %#x is writing into an unsupported special register %#x. "
                    "Ignoring the instruction.",
                    self.addr,
                    dest_spec_reg,
                )
        else:
            log.debug("[thumb] tMSR at %#x is writing SPSR. Ignoring the instruction. FixMe.", self.addr)
        log.debug(
            "[thumb] Spotting an tMSR instruction at %#x.  This is not fully tested.  Prepare for errors.", self.addr
        )


class Instruction_tMRS(ThumbInstruction):
    name = "tMRS"
    bin_format = "10x0mmmmxxxxxxxx11110011111Rrrrr"

    def compute_result(self):  # pylint: disable=arguments-differ
        spec_reg = int(self.data["x"], 2)
        dest_reg = f"r{int(self.data['m'], 2)}"

        # Reading from CPSR
        if self.data["R"] == "0":
            # See special registers constants here:
            # https://github.com/aquynh/capstone/blob/45bec1a691e455b864f7e4d394711a467e5493dc/arch/ARM/ARMInstPrinter.c#L1654
            if spec_reg == 8:
                # We move the SP and call it a day.
                src = self.get("sp", Type.int_32)
                self.put(src, dest_reg)
            elif spec_reg == 16:
                src = self.get("primask", Type.int_32)
                self.put(src, dest_reg)
            else:
                log.debug(
                    "[thumb] FIXME: tMRS at %#x is using the unsupported special register %#x. "
                    "Ignoring the instruction.",
                    self.addr,
                    spec_reg,
                )
        else:
            log.debug("[thumb] tMRS at %#x is reading from SPSR. Ignoring the instruction. FixMe.", self.addr)
            log.debug("[thumb] Ignoring tMRS instruction at %#x.", self.addr)
        log.debug(
            "[thumb] Spotting an tMRS instruction at %#x.  This is not fully tested.  Prepare for errors.", self.addr
        )


class Instruction_tDMB(ThumbInstruction):
    name = "DMB"
    bin_format = "100011110101xxxx1111001110111111"

    def compute_result(self):  # pylint: disable=arguments-differ
        # TODO haha lol yeah right
        log.debug("[thumb] Ignoring DMB instruction at %#x.", self.addr)


class Instruction_WFI(ThumbInstruction):
    name = "WFI"
    bin_format = "10111111001a0000"
    # 1011111100110000

    def compute_result(self):  # pylint: disable=arguments-differ
        log.debug("[thumb] Ignoring WFI instruction at %#x.", self.addr)


class ARMSpotter(GymratLifter):
    arm_instrs = [
        Instruction_MRC,
        Instruction_MCR,
        Instruction_MSR,
        Instruction_MRS,
        Instruction_STM,
        Instruction_LDM,
        Instruction_STC,
        Instruction_LDC,
        Instruction_CDP,
    ]
    thumb_instrs = [
        Instruction_tCPSID,
        Instruction_tMSR,
        Instruction_tMRS,
        Instruction_WFI,
        Instruction_tDMB,
        Instruction_STC_THUMB,
        Instruction_LDC_THUMB,
    ]

    def __init__(self, arch: Arch, addr: int):
        super().__init__(arch, addr)
        self.thumb: bool = False

    def _lift(self):
        if self.irsb.addr & 1:
            # Thumb!
            self.instrs = self.thumb_instrs
            self.thumb = True
        else:
            self.instrs = self.arm_instrs
            self.thumb = False
        super()._lift()


================================================
FILE: pyvex/lifting/gym/x86_spotter.py
================================================
import logging

from pyvex.lifting.util import GymratLifter, Instruction, JumpKind, Type

log = logging.getLogger(__name__)

# pylint: disable=missing-class-docstring


class Instruction_SWAPGS(Instruction):
    name = "SWAPGS"
    bin_format = "000011110000000111111000"  # 0f 01 f8

    def compute_result(self, *args):
        pass  # TODO check for priv mode


class Instruction_SYSRET(Instruction):
    name = "SYSRET"
    bin_format = "010010000000111100000111"  # 48 04 07

    def compute_result(self, *args):
        result = self.dirty(Type.int_64, "%sg_dirtyhelper_SYSRET" % self.arch.name.lower(), ())
        self.jump(None, result, JumpKind.Ret)


class Instruction_IRETQ(Instruction):
    name = "IRETQ"
    bin_format = "0100100011001111"  # 48 cf

    def compute_result(self, *args):
        result = self.dirty(Type.int_64, "%sg_dirtyhelper_IRETQ" % self.arch.name.lower(), ())
        self.jump(None, result, JumpKind.Ret)


class Instruction_RDMSR(Instruction):
    name = "RDMSR"
    bin_format = "0000111100110010"  # 0f 32

    def compute_result(self, *args):
        ecx = self.get("ecx", Type.int_32)
        result = self.dirty(Type.int_64, "%sg_dirtyhelper_RDMSR" % self.arch.name.lower(), (ecx,))
        edx = result.narrow_high(Type.int_32)
        eax = result.narrow_low(Type.int_32)
        if self.arch.bits == 32:
            self.put(eax, "eax")
            self.put(edx, "edx")
        else:
            self.put(eax.widen_unsigned(Type.int_64), "rax")
            self.put(edx.widen_unsigned(Type.int_64), "rdx")


class Instruction_XGETBV(Instruction):
    name = "XGETBV"
    bin_format = "000011110000000111010000"  # 0f 01 d0

    def compute_result(self, *args):
        ecx = self.get("ecx", Type.int_32)
        result = self.dirty(Type.int_64, "%sg_dirtyhelper_XGETBV" % self.arch.name.lower(), (ecx,))
        edx = result.narrow_high(Type.int_32)
        eax = result.narrow_low(Type.int_32)
        if self.arch.bits == 32:
            self.put(eax, "eax")
            self.put(edx, "edx")
        else:
            self.put(eax.widen_unsigned(Type.int_64), "rax")
            self.put(edx.widen_unsigned(Type.int_64), "rdx")


class Instruction_AAM(Instruction):
    name = "AAM"
    bin_format = "11010100iiiiiiii"

    # From https://www.felixcloutier.com/x86/aam
    def compute_result(self):  # pylint: disable=arguments-differ
        base = self.constant(int(self.data["i"], 2), Type.int_8)
        temp_al = self.get("al", Type.int_8)
        temp_ah = temp_al // base
        temp_al = temp_al % base
        self.put(temp_ah, "ah")
        self.put(temp_al, "al")
        log.debug(
            "The generalized AAM instruction is not supported by VEX, and is handled specially by pyvex."
            " It has no flag handling at present.  See pyvex/lifting/gym/x86_spotter.py for details"
        )

    # TODO: Flags


class Instruction_AAD(Instruction):
    name = "AAD"
    bin_format = "11010101iiiiiiii"

    # From https://www.felixcloutier.com/x86/aad
    def compute_result(self):  # pylint: disable=arguments-differ
        base = self.constant(int(self.data["i"], 2), Type.int_8)
        temp_al = self.get("al", Type.int_8)
        temp_ah = self.get("ah", Type.int_8)
        temp_al = (temp_al + (temp_ah * base)) & 0xFF
        temp_ah = self.constant(0, Type.int_8)
        self.put(temp_ah, "ah")
        self.put(temp_al, "al")
        log.debug(
            "The generalized AAD instruction is not supported by VEX, and is handled specially by pyvex."
            " It has no flag handling at present.  See pyvex/lifting/gym/x86_spotter.py for details"
        )

    # TODO: Flags


class AMD64Spotter(GymratLifter):
    instrs = [
        Instruction_RDMSR,
        Instruction_XGETBV,
        Instruction_AAD,
        Instruction_AAM,
        Instruction_SWAPGS,
        Instruction_IRETQ,
        Instruction_SYSRET,
    ]


class X86Spotter(GymratLifter):
    instrs = [
        Instruction_RDMSR,
        Instruction_XGETBV,
        Instruction_AAD,
        Instruction_AAM,
    ]


================================================
FILE: pyvex/lifting/libvex.py
================================================
import logging
import threading
from typing import TYPE_CHECKING

from pyvex.errors import LiftingException
from pyvex.native import ffi, pvc
from pyvex.types import CLiftSource, LibvexArch

from .lift_function import Lifter

log = logging.getLogger("pyvex.lifting.libvex")

_libvex_lock = threading.Lock()

LIBVEX_SUPPORTED_ARCHES = {
    "X86",
    "AMD64",
    "MIPS32",
    "MIPS64",
    "ARM",
    "ARMEL",
    "ARMHF",
    "ARMCortexM",
    "AARCH64",
    "PPC32",
    "PPC64",
    "S390X",
    "RISCV64",
}

VEX_MAX_INSTRUCTIONS = 99
VEX_MAX_BYTES = 5000


class VexRegisterUpdates:
    VexRegUpd_INVALID = 0x700
    VexRegUpdSpAtMemAccess = 0x701
    VexRegUpdUnwindregsAtMemAccess = 0x702
    VexRegUpdAllregsAtMemAccess = 0x703
    VexRegUpdAllregsAtEachInsn = 0x704
    VexRegUpdLdAllregsAtEachInsn = 0x705


class LibVEXLifter(Lifter):
    __slots__ = ()

    REQUIRE_DATA_C = True

    @staticmethod
    def get_vex_log():
        return bytes(ffi.buffer(pvc.msg_buffer, pvc.msg_current_size)).decode() if pvc.msg_buffer != ffi.NULL else None

    def _lift(self):
        if TYPE_CHECKING:
            assert isinstance(self.irsb.arch, LibvexArch)
            assert isinstance(self.data, CLiftSource)
        try:
            _libvex_lock.acquire()

            pvc.log_level = log.getEffectiveLevel()
            vex_arch = getattr(pvc, self.irsb.arch.vex_arch, None)
            assert vex_arch is not None

            if self.bytes_offset is None:
                self.bytes_offset = 0

            if self.max_bytes is None or self.max_bytes > VEX_MAX_BYTES:
                max_bytes = VEX_MAX_BYTES
            else:
                max_bytes = self.max_bytes

            if self.max_inst is None or self.max_inst > VEX_MAX_INSTRUCTIONS:
                max_inst = VEX_MAX_INSTRUCTIONS
            else:
                max_inst = self.max_inst

            strict_block_end = self.strict_block_end
            if strict_block_end is None:
                strict_block_end = True

            if self.cross_insn_opt:
                px_control = VexRegisterUpdates.VexRegUpdUnwindregsAtMemAccess
            else:
                px_control = VexRegisterUpdates.VexRegUpdLdAllregsAtEachInsn

            self.irsb.arch.vex_archinfo["hwcache_info"]["caches"] = ffi.NULL
            lift_r = pvc.vex_lift(
                vex_arch,
                self.irsb.arch.vex_archinfo,
                self.data + self.bytes_offset,
                self.irsb.addr,
                max_inst,
                max_bytes,
                self.opt_level,
                self.traceflags,
                self.allow_arch_optimizations,
                strict_block_end,
                1 if self.collect_data_refs else 0,
                1 if self.load_from_ro_regions else 0,
                1 if self.const_prop else 0,
                px_control,
                self.bytes_offset,
            )
            log_str = self.get_vex_log()
            if lift_r == ffi.NULL:
                raise LiftingException("libvex: unknown error" if log_str is None else log_str)
            else:
                if log_str is not None:
                    log.debug(log_str)

            self.irsb._from_c(lift_r, skip_stmts=self.skip_stmts)
            if self.irsb.size == 0:
                log.debug("raising lifting exception")
                raise LiftingException("libvex: could not decode any instructions @ 0x%x" % self.addr)
        finally:
            _libvex_lock.release()
            self.irsb.arch.vex_archinfo["hwcache_info"]["caches"] = None


================================================
FILE: pyvex/lifting/lift_function.py
================================================
import logging
from collections import defaultdict
from typing import DefaultDict

from pyvex import const
from pyvex.block import IRSB
from pyvex.const import vex_int_class
from pyvex.errors import LiftingException, NeedStatementsNotification, PyVEXError, SkipStatementsError
from pyvex.expr import Const
from pyvex.native import ffi
from pyvex.types import LiftSource, PyLiftSource

from .lifter import Lifter
from .post_processor import Postprocessor

log = logging.getLogger(__name__)

lifters: DefaultDict[str, list[type[Lifter]]] = defaultdict(list)
postprocessors: DefaultDict[str, list[type[Postprocessor]]] = defaultdict(list)


def lift(
    data: LiftSource,
    addr,
    arch,
    max_bytes=None,
    max_inst=None,
    bytes_offset=0,
    opt_level=1,
    traceflags=0,
    strict_block_end=True,
    inner=False,
    skip_stmts=False,
    collect_data_refs=False,
    cross_insn_opt=True,
    load_from_ro_regions=False,
    const_prop=False,
):
    """
    Recursively lifts blocks using the registered lifters and postprocessors. Tries each lifter in the order in
    which they are registered on the data to lift.

    If a lifter raises a LiftingException on the data, it is skipped.
    If it succeeds and returns a block with a jumpkind of Ijk_NoDeco
Download .txt
gitextract_782bwflj/

├── .git-blame-ignore-revs
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   ├── config.yml
│   │   ├── feature-request.yml
│   │   └── question.yml
│   └── workflows/
│       ├── ci.yml
│       ├── cifuzz.yml
│       └── nightly-ci.yml
├── .gitignore
├── .gitmodules
├── .pre-commit-config.yaml
├── .readthedocs.yml
├── CMakeLists.txt
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs/
│   ├── Makefile
│   ├── api.rst
│   ├── conf.py
│   ├── index.rst
│   ├── make.bat
│   └── quickstart.rst
├── fuzzing/
│   ├── build.sh
│   ├── enhanced_fdp.py
│   └── irsb_fuzzer.py
├── make_ffi.py
├── pyproject.toml
├── pyvex/
│   ├── __init__.py
│   ├── _register_info.py
│   ├── arches.py
│   ├── block.py
│   ├── const.py
│   ├── const_val.py
│   ├── data_ref.py
│   ├── enums.py
│   ├── errors.py
│   ├── expr.py
│   ├── lifting/
│   │   ├── __init__.py
│   │   ├── gym/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── aarch64_spotter.py
│   │   │   ├── arm_spotter.py
│   │   │   └── x86_spotter.py
│   │   ├── libvex.py
│   │   ├── lift_function.py
│   │   ├── lifter.py
│   │   ├── post_processor.py
│   │   ├── util/
│   │   │   ├── __init__.py
│   │   │   ├── instr_helper.py
│   │   │   ├── lifter_helper.py
│   │   │   ├── syntax_wrapper.py
│   │   │   └── vex_helper.py
│   │   └── zerodivision.py
│   ├── native.py
│   ├── py.typed
│   ├── stmt.py
│   ├── types.py
│   └── utils.py
├── pyvex_c/
│   ├── LICENSE
│   ├── README
│   ├── analysis.c
│   ├── e4c_lite.h
│   ├── logging.c
│   ├── logging.h
│   ├── postprocess.c
│   ├── pyvex.c
│   ├── pyvex.def
│   ├── pyvex.h
│   └── pyvex_internal.h
└── tests/
    ├── test_arm_postprocess.py
    ├── test_gym.py
    ├── test_irsb_property_caching.py
    ├── test_lift.py
    ├── test_mips32_postprocess.py
    ├── test_pyvex.py
    ├── test_s390x_exrl.py
    ├── test_s390x_lochi.py
    ├── test_s390x_vl.py
    ├── test_spotter.py
    └── test_ud2.py
Download .txt
SYMBOL INDEX (738 symbols across 44 files)

FILE: fuzzing/enhanced_fdp.py
  class EnhancedFuzzedDataProvider (line 23) | class EnhancedFuzzedDataProvider(FuzzedDataProvider):
    method _consume_random_count (line 28) | def _consume_random_count(self) -> int:
    method ConsumeRandomBytes (line 34) | def ConsumeRandomBytes(self) -> bytes:
    method ConsumeRemainingBytes (line 41) | def ConsumeRemainingBytes(self) -> bytes:
    method ConsumeRandomString (line 47) | def ConsumeRandomString(self) -> str:
    method ConsumeRemainingString (line 54) | def ConsumeRemainingString(self) -> str:
    method PickValueInEnum (line 60) | def PickValueInEnum(self, enum):

FILE: fuzzing/irsb_fuzzer.py
  function nostdout (line 35) | def nostdout():
  class SupportedOptLevels (line 64) | class SupportedOptLevels(IntEnum):
  function consume_random_arch (line 75) | def consume_random_arch(fdp: atheris.FuzzedDataProvider) -> pyvex.arches...
  function TestOneInput (line 79) | def TestOneInput(data: bytes):
  function main (line 109) | def main():

FILE: make_ffi.py
  function find_good_scan (line 14) | def find_good_scan(questionable):
  function doit (line 69) | def doit(vex_path):
  function get_guest_offsets (line 133) | def get_guest_offsets(vex_path):

FILE: pyvex/arches.py
  class PyvexArch (line 7) | class PyvexArch:
    method __init__ (line 12) | def __init__(self, name: str, bits: int, memory_endness: str, instruct...
    method __repr__ (line 53) | def __repr__(self):
    method vex_name_small (line 57) | def vex_name_small(self):
    method translate_register_name (line 60) | def translate_register_name(self, offset, size=None):  # pylint: disab...
    method get_register_offset (line 69) | def get_register_offset(self, name: str) -> int:

FILE: pyvex/block.py
  class IRSB (line 32) | class IRSB(VEXObject):
    method __init__ (line 76) | def __init__(
    method empty_block (line 169) | def empty_block(arch, addr, statements=None, nxt=None, tyenv=None, jum...
    method tyenv (line 175) | def tyenv(self) -> "IRTypeEnv":
    method tyenv (line 181) | def tyenv(self, v):
    method has_statements (line 185) | def has_statements(self) -> bool:
    method exit_statements (line 189) | def exit_statements(self) -> tuple[tuple[int, int, IRStmt], ...]:
    method copy (line 210) | def copy(self) -> "IRSB":
    method extend (line 213) | def extend(self, extendwith) -> None:
    method invalidate_direct_next (line 289) | def invalidate_direct_next(self) -> None:
    method pp (line 292) | def pp(self) -> None:
    method __repr__ (line 298) | def __repr__(self):
    method __str__ (line 301) | def __str__(self):
    method __eq__ (line 304) | def __eq__(self, other):
    method __hash__ (line 314) | def __hash__(self):
    method typecheck (line 317) | def typecheck(self) -> bool:
    method from_c (line 359) | def from_c(c_irsb, mem_addr, arch) -> "IRSB":
    method from_py (line 365) | def from_py(tyenv, stmts, next_expr, jumpkind, mem_addr, arch) -> "IRSB":
    method stmts_used (line 381) | def stmts_used(self) -> int:
    method offsIP (line 387) | def offsIP(self) -> int:
    method direct_next (line 391) | def direct_next(self):
    method expressions (line 397) | def expressions(self):
    method instructions (line 406) | def instructions(self):
    method instruction_addresses (line 418) | def instruction_addresses(self) -> tuple[int, ...]:
    method size (line 432) | def size(self):
    method operations (line 441) | def operations(self):
    method all_constants (line 452) | def all_constants(self):
    method constants (line 460) | def constants(self):
    method constant_jump_targets (line 467) | def constant_jump_targets(self):
    method constant_jump_targets_and_jumpkinds (line 484) | def constant_jump_targets_and_jumpkinds(self):
    method _pp_str (line 504) | def _pp_str(self) -> str:
    method _is_defaultexit_direct_jump (line 534) | def _is_defaultexit_direct_jump(self):
    method _from_c (line 548) | def _from_c(self, lift_r, skip_stmts=False):
    method _set_attributes (line 598) | def _set_attributes(
    method _from_py (line 623) | def _from_py(self, irsb):
  class IRTypeEnv (line 638) | class IRTypeEnv(VEXObject):
    method __init__ (line 649) | def __init__(self, arch, types=None):
    method __str__ (line 654) | def __str__(self):
    method lookup (line 657) | def lookup(self, tmp: int) -> str:
    method sizeof (line 666) | def sizeof(self, tmp):
    method add (line 669) | def add(self, ty):
    method types_used (line 677) | def types_used(self):
    method _from_c (line 681) | def _from_c(arch, c_tyenv):
    method _to_c (line 685) | def _to_c(tyenv):
    method typecheck (line 691) | def typecheck(self):

FILE: pyvex/const.py
  class IRConst (line 11) | class IRConst(VEXObject, ABC):
    method pp (line 20) | def pp(self):
    method value (line 24) | def value(self) -> int:
    method _from_c (line 28) | def _from_c(c_const):
    method _to_c (line 42) | def _to_c(cls, const):
    method __eq__ (line 52) | def __eq__(self, other):
    method __hash__ (line 57) | def __hash__(self):
  class U1 (line 61) | class U1(IRConst):
    method __init__ (line 70) | def __init__(self, value):
    method __str__ (line 73) | def __str__(self):
    method _from_c (line 77) | def _from_c(c_const):
  class U8 (line 81) | class U8(IRConst):
    method __init__ (line 90) | def __init__(self, value):
    method __str__ (line 93) | def __str__(self):
    method _from_c (line 97) | def _from_c(c_const):
  class U16 (line 104) | class U16(IRConst):
    method __init__ (line 113) | def __init__(self, value):
    method __str__ (line 116) | def __str__(self):
    method _from_c (line 120) | def _from_c(c_const):
  class U32 (line 132) | class U32(IRConst):
    method __init__ (line 141) | def __init__(self, value: int):
    method __str__ (line 144) | def __str__(self):
    method _from_c (line 148) | def _from_c(c_const):
  class U64 (line 160) | class U64(IRConst):
    method __init__ (line 169) | def __init__(self, value):
    method __str__ (line 172) | def __str__(self):
    method _from_c (line 176) | def _from_c(c_const):
  function vex_int_class (line 191) | def vex_int_class(size):
  class F32 (line 213) | class F32(IRConst):
    method __init__ (line 222) | def __init__(self, value):
    method __str__ (line 225) | def __str__(self):
    method _from_c (line 229) | def _from_c(c_const):
  class F32i (line 233) | class F32i(IRConst):
    method __init__ (line 242) | def __init__(self, value):
    method __str__ (line 245) | def __str__(self):
    method _from_c (line 249) | def _from_c(c_const):
  class F64 (line 253) | class F64(IRConst):
    method __init__ (line 262) | def __init__(self, value):
    method __str__ (line 265) | def __str__(self):
    method _from_c (line 269) | def _from_c(c_const):
  class F64i (line 273) | class F64i(IRConst):
    method __init__ (line 282) | def __init__(self, value):
    method __str__ (line 285) | def __str__(self):
    method _from_c (line 289) | def _from_c(c_const):
  class V128 (line 293) | class V128(IRConst):
    method __init__ (line 302) | def __init__(self, value):
    method __str__ (line 305) | def __str__(self):
    method _from_c (line 311) | def _from_c(c_const):
  class V256 (line 320) | class V256(IRConst):
    method __init__ (line 329) | def __init__(self, value):
    method __str__ (line 332) | def __str__(self):
    method _from_c (line 337) | def _from_c(c_const):
  function is_int_ty (line 356) | def is_int_ty(ty):
  function is_int_tag (line 361) | def is_int_tag(tag):
  function get_tag_size (line 366) | def get_tag_size(tag):
  function get_type_size (line 377) | def get_type_size(ty):
  function get_type_spec_size (line 391) | def get_type_spec_size(ty):
  function ty_to_const_class (line 407) | def ty_to_const_class(ty):
  function tag_to_const_class (line 418) | def tag_to_const_class(tag):

FILE: pyvex/const_val.py
  class ConstVal (line 1) | class ConstVal:
    method __init__ (line 16) | def __init__(self, tmp: int, value: int, stmt_idx: int):
    method __repr__ (line 21) | def __repr__(self):
    method from_c (line 25) | def from_c(cls, r):

FILE: pyvex/data_ref.py
  function data_ref_type_str (line 1) | def data_ref_type_str(dref_enum):
  class DataRef (line 17) | class DataRef:
    method __init__ (line 30) | def __init__(self, data_addr, data_size, data_type, stmt_idx, ins_addr):
    method data_type_str (line 38) | def data_type_str(self):
    method __repr__ (line 44) | def __repr__(self):
    method from_c (line 54) | def from_c(cls, r):

FILE: pyvex/enums.py
  class VEXObject (line 7) | class VEXObject:
    method __eq__ (line 14) | def __eq__(self, other):
    method __hash__ (line 23) | def __hash__(self):
  class IRCallee (line 31) | class IRCallee(VEXObject):
    method __init__ (line 38) | def __init__(self, regparms, name, mcx_mask):
    method __str__ (line 44) | def __str__(self):
    method _from_c (line 48) | def _from_c(c_callee):
    method _to_c (line 57) | def _to_c(callee):  # pylint: disable=unused-argument
  class IRRegArray (line 68) | class IRRegArray(VEXObject):
    method __init__ (line 80) | def __init__(self, base, elemTy, nElems):
    method __str__ (line 86) | def __str__(self):
    method _from_c (line 90) | def _from_c(c_arr):
    method _to_c (line 94) | def _to_c(arr):
  function get_enum_from_int (line 104) | def get_enum_from_int(i):
  function get_int_from_enum (line 108) | def get_int_from_enum(e):
  function _add_enum (line 115) | def _add_enum(s, i=None):  # TODO get rid of this
  function vex_endness_from_string (line 136) | def vex_endness_from_string(endness_str):
  function default_vex_archinfo (line 140) | def default_vex_archinfo() -> dict[str, Any]:

FILE: pyvex/errors.py
  class PyVEXError (line 1) | class PyVEXError(Exception):
  class SkipStatementsError (line 5) | class SkipStatementsError(PyVEXError):
  class LiftingException (line 14) | class LiftingException(Exception):
  class NeedStatementsNotification (line 18) | class NeedStatementsNotification(LiftingException):

FILE: pyvex/expr.py
  class IRExpr (line 18) | class IRExpr(VEXObject):
    method pp (line 28) | def pp(self):
    method __str__ (line 31) | def __str__(self):
    method _pp_str (line 34) | def _pp_str(self) -> str:
    method child_expressions (line 38) | def child_expressions(self) -> list[IRExpr]:
    method constants (line 51) | def constants(self):
    method result_size (line 64) | def result_size(self, tyenv: IRTypeEnv):
    method result_type (line 67) | def result_type(self, tyenv: IRTypeEnv):
    method replace_expression (line 70) | def replace_expression(self, replacements):
    method _from_c (line 103) | def _from_c(c_expr) -> IRExpr | None:
    method _to_c (line 115) | def _to_c(expr):
    method typecheck (line 121) | def typecheck(self, tyenv):
  class Binder (line 125) | class Binder(IRExpr):
    method __init__ (line 134) | def __init__(self, binder):
    method _pp_str (line 137) | def _pp_str(self):
    method _from_c (line 141) | def _from_c(c_expr):
    method _to_c (line 145) | def _to_c(expr):
    method result_type (line 148) | def result_type(self, tyenv):
  class VECRET (line 152) | class VECRET(IRExpr):
    method _pp_str (line 157) | def _pp_str(self):
    method _from_c (line 161) | def _from_c(c_expr):
    method _to_c (line 165) | def _to_c(expr):
    method result_type (line 168) | def result_type(self, tyenv):
  class GSPTR (line 172) | class GSPTR(IRExpr):
    method _pp_str (line 177) | def _pp_str(self):
    method _from_c (line 181) | def _from_c(c_expr):
    method _to_c (line 185) | def _to_c(expr):
    method result_type (line 188) | def result_type(self, tyenv):
  class GetI (line 192) | class GetI(IRExpr):
    method __init__ (line 201) | def __init__(self, descr, ix, bias):
    method description (line 207) | def description(self):
    method index (line 211) | def index(self):
    method _pp_str (line 214) | def _pp_str(self):
    method _from_c (line 218) | def _from_c(c_expr):
    method _to_c (line 225) | def _to_c(expr):
    method result_type (line 228) | def result_type(self, tyenv):
  class RdTmp (line 232) | class RdTmp(IRExpr):
    method __init__ (line 241) | def __init__(self, tmp):
    method _pp_str (line 244) | def _pp_str(self):
    method tmp (line 248) | def tmp(self):
    method _from_c (line 252) | def _from_c(c_expr):
    method _to_c (line 257) | def _to_c(expr):
    method get_instance (line 261) | def get_instance(tmp):
    method replace_expression (line 267) | def replace_expression(self, replacements):
    method result_type (line 271) | def result_type(self, tyenv):
    method __hash__ (line 274) | def __hash__(self):
  class Get (line 281) | class Get(IRExpr):
    method __init__ (line 290) | def __init__(self, offset: int, ty: str, ty_int: int | None = None):
    method ty (line 298) | def ty(self):
    method type (line 302) | def type(self):
    method _pp_str (line 305) | def _pp_str(self):
    method pp_str_with_name (line 308) | def pp_str_with_name(self, reg_name: str):
    method _from_c (line 314) | def _from_c(c_expr):
    method _to_c (line 318) | def _to_c(expr):
    method result_type (line 321) | def result_type(self, tyenv):
    method __hash__ (line 324) | def __hash__(self):
  class Qop (line 328) | class Qop(IRExpr):
    method __init__ (line 337) | def __init__(self, op, args):
    method _pp_str (line 341) | def _pp_str(self):
    method child_expressions (line 345) | def child_expressions(self):
    method _from_c (line 351) | def _from_c(c_expr):
    method _to_c (line 366) | def _to_c(expr):
    method result_type (line 369) | def result_type(self, tyenv):
    method typecheck (line 372) | def typecheck(self, tyenv):  # TODO change all this to use PyvexTypeEr...
  class Triop (line 397) | class Triop(IRExpr):
    method __init__ (line 406) | def __init__(self, op, args):
    method _pp_str (line 410) | def _pp_str(self):
    method child_expressions (line 414) | def child_expressions(self):
    method _from_c (line 420) | def _from_c(c_expr):
    method _to_c (line 430) | def _to_c(expr):
    method result_type (line 433) | def result_type(self, tyenv):
    method typecheck (line 436) | def typecheck(self, tyenv):
  class Binop (line 457) | class Binop(IRExpr):
    method __init__ (line 466) | def __init__(self, op, args, op_int=None):
    method _pp_str (line 471) | def _pp_str(self):
    method op (line 475) | def op(self):
    method child_expressions (line 481) | def child_expressions(self):
    method _from_c (line 487) | def _from_c(c_expr):
    method _to_c (line 495) | def _to_c(expr):
    method result_type (line 498) | def result_type(self, tyenv):
    method typecheck (line 501) | def typecheck(self, tyenv):
  class Unop (line 519) | class Unop(IRExpr):
    method __init__ (line 528) | def __init__(self, op: str, args: list[IRExpr]):
    method _pp_str (line 532) | def _pp_str(self):
    method child_expressions (line 536) | def child_expressions(self):
    method _from_c (line 542) | def _from_c(c_expr):
    method _to_c (line 546) | def _to_c(expr):
    method result_type (line 549) | def result_type(self, tyenv):
    method typecheck (line 552) | def typecheck(self, tyenv):
  class Load (line 565) | class Load(IRExpr):
    method __init__ (line 574) | def __init__(self, end, ty, addr):
    method endness (line 580) | def endness(self):
    method type (line 584) | def type(self):
    method _pp_str (line 587) | def _pp_str(self):
    method _from_c (line 591) | def _from_c(c_expr):
    method _to_c (line 599) | def _to_c(expr):
    method result_type (line 602) | def result_type(self, tyenv):
    method typecheck (line 605) | def typecheck(self, tyenv):
  class Const (line 615) | class Const(IRExpr):
    method __init__ (line 624) | def __init__(self, con: IRConst):
    method _pp_str (line 627) | def _pp_str(self):
    method con (line 631) | def con(self) -> IRConst:
    method _from_c (line 635) | def _from_c(c_expr):
    method _to_c (line 640) | def _to_c(expr):
    method get_instance (line 644) | def get_instance(con):
    method result_type (line 649) | def result_type(self, tyenv):
  class ITE (line 661) | class ITE(IRExpr):
    method __init__ (line 670) | def __init__(self, cond, iffalse, iftrue):
    method _pp_str (line 675) | def _pp_str(self):
    method _from_c (line 679) | def _from_c(c_expr):
    method _to_c (line 687) | def _to_c(expr):
    method result_type (line 690) | def result_type(self, tyenv):
    method typecheck (line 693) | def typecheck(self, tyenv):
  class CCall (line 712) | class CCall(IRExpr):
    method __init__ (line 721) | def __init__(self, retty, cee, args):
    method ret_type (line 727) | def ret_type(self):
    method callee (line 731) | def callee(self):
    method _pp_str (line 734) | def _pp_str(self):
    method child_expressions (line 738) | def child_expressions(self):
    method _from_c (line 744) | def _from_c(c_expr):
    method _to_c (line 757) | def _to_c(expr):
    method result_type (line 762) | def result_type(self, tyenv):
  function get_op_retty (line 766) | def get_op_retty(op):
  function _request_op_type_from_cache (line 773) | def _request_op_type_from_cache(op):
  function _request_op_type_from_libvex (line 777) | def _request_op_type_from_libvex(op):
  class PyvexOpMatchException (line 799) | class PyvexOpMatchException(Exception):
  class PyvexTypeErrorException (line 803) | class PyvexTypeErrorException(Exception):
  function int_type_for_size (line 807) | def int_type_for_size(size):
  function unop_signature (line 822) | def unop_signature(op):
  function binop_signature (line 831) | def binop_signature(op):
  function shift_signature (line 840) | def shift_signature(op):
  function cmp_signature (line 851) | def cmp_signature(op):
  function mull_signature (line 863) | def mull_signature(op):
  function half_signature (line 873) | def half_signature(op):
  function cast_signature (line 886) | def cast_signature(op):
  function _request_polymorphic_op_type (line 906) | def _request_polymorphic_op_type(op):
  function op_arg_types (line 921) | def op_arg_types(op):
  function tag_to_expr_class (line 947) | def tag_to_expr_class(tag):
  function enum_to_expr_class (line 962) | def enum_to_expr_class(tag_enum):

FILE: pyvex/lifting/gym/aarch64_spotter.py
  class Aarch64Instruction (line 9) | class Aarch64Instruction(Instruction):  # pylint: disable=abstract-method
  class Instruction_SYSL (line 15) | class Instruction_SYSL(Aarch64Instruction):
    method compute_result (line 19) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_MSR (line 23) | class Instruction_MSR(Aarch64Instruction):
    method compute_result (line 27) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_MRS (line 31) | class Instruction_MRS(Aarch64Instruction):
    method compute_result (line 35) | def compute_result(self):  # pylint: disable=arguments-differ
  class AARCH64Spotter (line 39) | class AARCH64Spotter(GymratLifter):

FILE: pyvex/lifting/gym/arm_spotter.py
  class ARMInstruction (line 13) | class ARMInstruction(Instruction):  # pylint: disable=abstract-method
    method match_instruction (line 20) | def match_instruction(self, data, bitstrm):
    method get_N (line 27) | def get_N(self):
    method get_C (line 34) | def get_C(self):
    method get_V (line 41) | def get_V(self):
    method get_Z (line 48) | def get_Z(self):
    method evaluate_condition (line 55) | def evaluate_condition(self):
    method _load_le_instr (line 101) | def _load_le_instr(self, bitstream: bitstring.ConstBitStream, numbits:...
  class Instruction_MRC (line 116) | class Instruction_MRC(ARMInstruction):
    method compute_result (line 126) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_MCR (line 133) | class Instruction_MCR(ARMInstruction):
    method compute_result (line 143) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_MSR (line 150) | class Instruction_MSR(ARMInstruction):
    method compute_result (line 156) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_MRS (line 164) | class Instruction_MRS(ARMInstruction):
    method compute_result (line 168) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_STM (line 176) | class Instruction_STM(ARMInstruction):
    method match_instruction (line 180) | def match_instruction(self, data, bitstrm):
    method compute_result (line 186) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_LDM (line 194) | class Instruction_LDM(ARMInstruction):
    method match_instruction (line 198) | def match_instruction(self, data, bitstrm):
    method compute_result (line 204) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_STC (line 238) | class Instruction_STC(ARMInstruction):
    method compute_result (line 242) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_STC_THUMB (line 247) | class Instruction_STC_THUMB(ARMInstruction):
    method compute_result (line 251) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_LDC (line 256) | class Instruction_LDC(ARMInstruction):
    method compute_result (line 260) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_LDC_THUMB (line 267) | class Instruction_LDC_THUMB(ARMInstruction):
    method compute_result (line 271) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_CDP (line 278) | class Instruction_CDP(Instruction):
    method compute_result (line 286) | def compute_result(self):  # pylint: disable=arguments-differ
  class ThumbInstruction (line 297) | class ThumbInstruction(Instruction):  # pylint: disable=abstract-method
    method mark_instruction_start (line 298) | def mark_instruction_start(self):
  class Instruction_tCPSID (line 302) | class Instruction_tCPSID(ThumbInstruction):
    method compute_result (line 306) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_tMSR (line 311) | class Instruction_tMSR(ThumbInstruction):
    method compute_result (line 315) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_tMRS (line 341) | class Instruction_tMRS(ThumbInstruction):
    method compute_result (line 345) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_tDMB (line 375) | class Instruction_tDMB(ThumbInstruction):
    method compute_result (line 379) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_WFI (line 384) | class Instruction_WFI(ThumbInstruction):
    method compute_result (line 389) | def compute_result(self):  # pylint: disable=arguments-differ
  class ARMSpotter (line 393) | class ARMSpotter(GymratLifter):
    method __init__ (line 415) | def __init__(self, arch: Arch, addr: int):
    method _lift (line 419) | def _lift(self):

FILE: pyvex/lifting/gym/x86_spotter.py
  class Instruction_SWAPGS (line 10) | class Instruction_SWAPGS(Instruction):
    method compute_result (line 14) | def compute_result(self, *args):
  class Instruction_SYSRET (line 18) | class Instruction_SYSRET(Instruction):
    method compute_result (line 22) | def compute_result(self, *args):
  class Instruction_IRETQ (line 27) | class Instruction_IRETQ(Instruction):
    method compute_result (line 31) | def compute_result(self, *args):
  class Instruction_RDMSR (line 36) | class Instruction_RDMSR(Instruction):
    method compute_result (line 40) | def compute_result(self, *args):
  class Instruction_XGETBV (line 53) | class Instruction_XGETBV(Instruction):
    method compute_result (line 57) | def compute_result(self, *args):
  class Instruction_AAM (line 70) | class Instruction_AAM(Instruction):
    method compute_result (line 75) | def compute_result(self):  # pylint: disable=arguments-differ
  class Instruction_AAD (line 90) | class Instruction_AAD(Instruction):
    method compute_result (line 95) | def compute_result(self):  # pylint: disable=arguments-differ
  class AMD64Spotter (line 111) | class AMD64Spotter(GymratLifter):
  class X86Spotter (line 123) | class X86Spotter(GymratLifter):

FILE: pyvex/lifting/libvex.py
  class VexRegisterUpdates (line 35) | class VexRegisterUpdates:
  class LibVEXLifter (line 44) | class LibVEXLifter(Lifter):
    method get_vex_log (line 50) | def get_vex_log():
    method _lift (line 53) | def _lift(self):

FILE: pyvex/lifting/lift_function.py
  function lift (line 22) | def lift(
  function register (line 291) | def register(lifter, arch_name):

FILE: pyvex/lifting/lifter.py
  class Lifter (line 7) | class Lifter:
    method __init__ (line 49) | def __init__(self, arch: Arch, addr: int):
    method lift (line 53) | def lift(
    method _lift (line 113) | def _lift(self):

FILE: pyvex/lifting/post_processor.py
  class Postprocessor (line 6) | class Postprocessor:
    method __init__ (line 7) | def __init__(self, irsb):
    method postprocess (line 10) | def postprocess(self):

FILE: pyvex/lifting/util/instr_helper.py
  class Instruction (line 13) | class Instruction(metaclass=abc.ABCMeta):
    method __init__ (line 73) | def __init__(self, bitstrm, arch, addr):
    method bin_format (line 88) | def bin_format(self) -> str:
    method name (line 97) | def name(self) -> str:
    method __call__ (line 104) | def __call__(self, irsb_c, past_instructions, future_instructions):
    method mark_instruction_start (line 107) | def mark_instruction_start(self):
    method fetch_operands (line 110) | def fetch_operands(self):  # pylint: disable=no-self-use
    method lift (line 117) | def lift(self, irsb_c: IRSBCustomizer, past_instructions, future_instr...
    method commit_result (line 138) | def commit_result(self, res):
    method compute_result (line 149) | def compute_result(self, *args):  # pylint: disable=unused-argument,no...
    method compute_flags (line 163) | def compute_flags(self, *args):
    method match_instruction (line 170) | def match_instruction(self, data, bitstrm):  # pylint: disable=unused-...
    method parse (line 181) | def parse(self, bitstrm):
    method bytewidth (line 215) | def bytewidth(self):
    method disassemble (line 220) | def disassemble(self):
    method load (line 231) | def load(self, addr, ty):
    method constant (line 242) | def constant(self, val, ty):
    method _lookup_register (line 256) | def _lookup_register(arch, reg):
    method get (line 266) | def get(self, reg, ty):
    method put (line 282) | def put(self, val, reg):
    method put_conditional (line 294) | def put_conditional(self, cond, valiftrue, valiffalse, reg):
    method store (line 311) | def store(self, val, addr):
    method jump (line 321) | def jump(self, condition, to_addr, jumpkind=JumpKind.Boring, ip_offset...
    method ite (line 365) | def ite(self, cond, t, f):
    method ccall (line 368) | def ccall(self, ret_type, func_name, args):
    method dirty (line 394) | def dirty(self, ret_type, func_name, args) -> VexValue:
    method _load_le_instr (line 421) | def _load_le_instr(self, bitstream: bitstring.ConstBitStream, numbits:...

FILE: pyvex/lifting/util/lifter_helper.py
  function is_empty (line 18) | def is_empty(bitstrm):
  class ParseError (line 26) | class ParseError(Exception):
  class GymratLifter (line 30) | class GymratLifter(Lifter):
    method __init__ (line 51) | def __init__(self, arch, addr):
    method create_bitstrm (line 58) | def create_bitstrm(self):
    method _decode_next_instruction (line 61) | def _decode_next_instruction(self, addr):
    method decode (line 82) | def decode(self):
    method _lift (line 106) | def _lift(self):
    method pp_disas (line 140) | def pp_disas(self):
    method error (line 148) | def error(self):
    method disassemble (line 151) | def disassemble(self):

FILE: pyvex/lifting/util/syntax_wrapper.py
  function checkparams (line 10) | def checkparams(rhstype=None):
  function vvifyresults (line 31) | def vvifyresults(f):
  class VexValue (line 41) | class VexValue:
    method __init__ (line 42) | def __init__(self, irsb_c: "IRSBCustomizer", rdt: "Union[RdTmp, Const]...
    method value (line 50) | def value(self):
    method signed (line 57) | def signed(self):
    method widen_unsigned (line 61) | def widen_unsigned(self, ty):
    method cast_to (line 65) | def cast_to(self, ty, signed=False, high=False):
    method widen_signed (line 69) | def widen_signed(self, ty):
    method narrow_high (line 73) | def narrow_high(self, ty):
    method narrow_low (line 77) | def narrow_low(self, ty):
    method __getitem__ (line 81) | def __getitem__(self, idx):
    method __setitem__ (line 94) | def __setitem__(self, idx, bval):
    method set_bit (line 100) | def set_bit(self, idx, bval):
    method set_bits (line 105) | def set_bits(self, idxsandvals):
    method ite (line 110) | def ite(self, iftrue, iffalse):
    method sar (line 116) | def sar(self, right):
    method __add__ (line 127) | def __add__(self, right):
    method __radd__ (line 131) | def __radd__(self, left):
    method __sub__ (line 136) | def __sub__(self, right):
    method __rsub__ (line 140) | def __rsub__(self, left):
    method __div__ (line 145) | def __div__(self, right):
    method __rdiv__ (line 152) | def __rdiv__(self, left):
    method __floordiv__ (line 156) | def __floordiv__(self, right):  # Note: nonprimitive
    method __rfloordiv__ (line 160) | def __rfloordiv__(self, left):
    method __truediv__ (line 164) | def __truediv__(self, right):  # Note: nonprimitive
    method __rtruediv__ (line 168) | def __rtruediv__(self, left):
    method __and__ (line 173) | def __and__(self, right):
    method __rand__ (line 177) | def __rand__(self, left):
    method __eq__ (line 182) | def __eq__(self, right):
    method __ne__ (line 187) | def __ne__(self, other):
    method __invert__ (line 192) | def __invert__(self):
    method __le__ (line 197) | def __le__(self, right):
    method __gt__ (line 205) | def __gt__(self, other):
    method __ge__ (line 213) | def __ge__(self, right):
    method __lshift__ (line 221) | def __lshift__(self, right):  # TODO put better type inference in irsb...
    method __lt__ (line 229) | def __lt__(self, right):
    method __mod__ (line 237) | def __mod__(self, right):  # Note: nonprimitive
    method __rmod__ (line 241) | def __rmod__(self, left):
    method __mul__ (line 246) | def __mul__(self, right):
    method __rmul__ (line 253) | def __rmul__(self, left):
    method __neg__ (line 258) | def __neg__(self):  # Note: nonprimitive
    method __or__ (line 266) | def __or__(self, right):
    method __ror__ (line 269) | def __ror__(self, left):
    method __pos__ (line 274) | def __pos__(self):
    method __rshift__ (line 279) | def __rshift__(self, right):
    method __rlshift__ (line 286) | def __rlshift__(self, left):
    method __rrshift__ (line 290) | def __rrshift__(self, left):
    method __xor__ (line 295) | def __xor__(self, right):
    method __rxor__ (line 298) | def __rxor__(self, left):
    method Constant (line 302) | def Constant(cls, irsb_c, val, ty):

FILE: pyvex/lifting/util/vex_helper.py
  class JumpKind (line 10) | class JumpKind:
  class TypeMeta (line 22) | class TypeMeta(type):
    method __getattr__ (line 25) | def __getattr__(self, name):
  class Type (line 34) | class Type(metaclass=TypeMeta):
  function get_op_format_from_const_ty (line 48) | def get_op_format_from_const_ty(ty):
  function make_format_op_generator (line 52) | def make_format_op_generator(fmt_string):
  function mkbinop (line 67) | def mkbinop(fstring):
  function mkunop (line 71) | def mkunop(fstring):
  function mkcmpop (line 75) | def mkcmpop(fstring_fragment, signedness=""):
  class IRSBCustomizer (line 85) | class IRSBCustomizer:
    method __init__ (line 118) | def __init__(self, irsb):
    method get_type (line 122) | def get_type(self, rdt):
    method _append_stmt (line 126) | def _append_stmt(self, stmt):
    method imark (line 129) | def imark(self, int_addr, int_length, int_delta=0):
    method get_reg (line 132) | def get_reg(self, regname):  # TODO move this into the lifter
    method put (line 135) | def put(self, expr_val, tuple_reg):
    method store (line 138) | def store(self, addr, expr):
    method noop (line 141) | def noop(self):
    method add_exit (line 144) | def add_exit(self, guard, dst, jk, ip):
    method goto (line 157) | def goto(self, addr):
    method ret (line 161) | def ret(self, addr):
    method call (line 165) | def call(self, addr):
    method _add_tmp (line 169) | def _add_tmp(self, t):
    method _rdtmp (line 172) | def _rdtmp(self, tmp):
    method _settmp (line 175) | def _settmp(self, expr):
    method rdreg (line 181) | def rdreg(self, reg, ty):
    method load (line 184) | def load(self, addr, ty):
    method op_ccall (line 187) | def op_ccall(self, retty, funcstr, args):
    method dirty (line 190) | def dirty(self, retty, funcstr, args):
    method ite (line 198) | def ite(self, condrdt, iftruerdt, iffalserdt):
    method mkconst (line 201) | def mkconst(self, val, ty):
    method op_generic (line 206) | def op_generic(self, Operation, op_generator):
    method op_binary (line 220) | def op_binary(self, op_format_str):
    method op_unary (line 223) | def op_unary(self, op_format_str):
    method cast_to (line 226) | def cast_to(self, rdt, tydest, signed=False, high=False):
    method op_to_one_bit (line 237) | def op_to_one_bit(self, rdt):
    method op_narrow_int (line 244) | def op_narrow_int(self, rdt, tydest, high_half=False):
    method op_widen_int (line 250) | def op_widen_int(self, rdt, tydest, signed=False):
    method op_widen_int_signed (line 256) | def op_widen_int_signed(self, rdt, tydest):
    method op_widen_int_unsigned (line 259) | def op_widen_int_unsigned(self, rdt, tydest):
    method get_msb (line 262) | def get_msb(self, tmp, ty):
    method get_bit (line 266) | def get_bit(self, rdt, idx):
    method op_extract_lsb (line 271) | def op_extract_lsb(self, rdt):
    method set_bit (line 275) | def set_bit(self, rdt, idx, bval):
    method set_bits (line 283) | def set_bits(self, rdt, idxsandvals):
    method get_rdt_width (line 300) | def get_rdt_width(self, rdt):

FILE: pyvex/lifting/zerodivision.py
  class ZeroDivisionPostProcessor (line 8) | class ZeroDivisionPostProcessor(Postprocessor):
    method postprocess (line 43) | def postprocess(self):

FILE: pyvex/native.py
  function _parse_ffi_str (line 17) | def _parse_ffi_str():
  function _find_c_lib (line 41) | def _find_c_lib():

FILE: pyvex/stmt.py
  class IRStmt (line 20) | class IRStmt(VEXObject):
    method pp (line 30) | def pp(self):
    method child_expressions (line 34) | def child_expressions(self) -> Iterator[IRExpr]:
    method expressions (line 45) | def expressions(self):
    method constants (line 49) | def constants(self):
    method _from_c (line 53) | def _from_c(c_stmt):
    method typecheck (line 63) | def typecheck(self, tyenv: IRTypeEnv) -> bool:  # pylint: disable=unus...
    method replace_expression (line 66) | def replace_expression(self, replacements):
    method __str__ (line 93) | def __str__(self):
    method pp_str (line 96) | def pp_str(self, reg_name=None, arch=None, tyenv=None) -> str:
  class NoOp (line 100) | class NoOp(IRStmt):
    method pp_str (line 109) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 113) | def _from_c(c_stmt):
  class IMark (line 117) | class IMark(IRStmt):
    method __init__ (line 128) | def __init__(self, addr: int, length: int, delta: int):
    method pp_str (line 133) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 137) | def _from_c(c_stmt):
  class AbiHint (line 141) | class AbiHint(IRStmt):
    method __init__ (line 150) | def __init__(self, base, length, nia):
    method pp_str (line 155) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 159) | def _from_c(c_stmt):
  class Put (line 165) | class Put(IRStmt):
    method __init__ (line 174) | def __init__(self, data: IRExpr, offset: int):
    method pp_str (line 179) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 189) | def _from_c(c_stmt):
    method typecheck (line 192) | def typecheck(self, tyenv):
  class PutI (line 196) | class PutI(IRStmt):
    method __init__ (line 205) | def __init__(self, descr, ix, data, bias):
    method pp_str (line 211) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 215) | def _from_c(c_stmt):
    method typecheck (line 223) | def typecheck(self, tyenv):
  class WrTmp (line 233) | class WrTmp(IRStmt):
    method __init__ (line 243) | def __init__(self, tmp, data: IRExpr):
    method pp_str (line 247) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 259) | def _from_c(c_stmt):
    method typecheck (line 262) | def typecheck(self, tyenv):
  class Store (line 272) | class Store(IRStmt):
    method __init__ (line 281) | def __init__(self, addr: IRExpr, data: IRExpr, end: str):
    method endness (line 287) | def endness(self):
    method pp_str (line 290) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 294) | def _from_c(c_stmt):
    method typecheck (line 301) | def typecheck(self, tyenv):
  class CAS (line 317) | class CAS(IRStmt):
    method __init__ (line 326) | def __init__(self, addr, dataLo, dataHi, expdLo, expdHi, oldLo, oldHi,...
    method endness (line 337) | def endness(self):
    method pp_str (line 340) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 346) | def _from_c(c_stmt):
    method typecheck (line 358) | def typecheck(self, tyenv):
  class LLSC (line 402) | class LLSC(IRStmt):
    method __init__ (line 412) | def __init__(self, addr: IRExpr, storedata: IRExpr, result: int, end: ...
    method endness (line 419) | def endness(self):
    method pp_str (line 422) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 429) | def _from_c(c_stmt):
    method typecheck (line 437) | def typecheck(self, tyenv):
  class MBE (line 461) | class MBE(IRStmt):
    method __init__ (line 466) | def __init__(self, event):
    method pp_str (line 469) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 473) | def _from_c(c_stmt):
  class Dirty (line 477) | class Dirty(IRStmt):
    method __init__ (line 482) | def __init__(self, cee, guard, args, tmp, mFx, mAddr, mSize, nFxState):
    method pp_str (line 492) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method child_expressions (line 498) | def child_expressions(self):
    method _from_c (line 506) | def _from_c(c_stmt):
  class Exit (line 527) | class Exit(IRStmt):
    method __init__ (line 536) | def __init__(self, guard: IRExpr, dst: IRConst, jk: str, offsIP: int):
    method jumpkind (line 543) | def jumpkind(self):
    method pp_str (line 546) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method child_expressions (line 556) | def child_expressions(self):
    method _from_c (line 560) | def _from_c(c_stmt):
    method typecheck (line 568) | def typecheck(self, tyenv):
  class LoadG (line 581) | class LoadG(IRStmt):
    method __init__ (line 590) | def __init__(self, end: str, cvt: str, dst: int, addr: IRExpr, alt: IR...
    method endness (line 606) | def endness(self):
    method pp_str (line 609) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 620) | def _from_c(c_stmt):
    method typecheck (line 630) | def typecheck(self, tyenv):
  class StoreG (line 659) | class StoreG(IRStmt):
    method __init__ (line 668) | def __init__(self, end, addr, data, guard):
    method endness (line 675) | def endness(self):
    method pp_str (line 678) | def pp_str(self, reg_name=None, arch=None, tyenv=None):
    method _from_c (line 682) | def _from_c(c_stmt):
    method typecheck (line 690) | def typecheck(self, tyenv):
  function tag_to_stmt_class (line 729) | def tag_to_stmt_class(tag):
  function enum_to_stmt_class (line 736) | def enum_to_stmt_class(tag_enum):

FILE: pyvex/types.py
  class Register (line 6) | class Register(Protocol):
  class Arch (line 14) | class Arch(Protocol):
    method translate_register_name (line 28) | def translate_register_name(self, offset: int, size: int | None = None...
    method get_register_offset (line 30) | def get_register_offset(self, name: str) -> int: ...
  class LibvexArch (line 34) | class LibvexArch(Protocol):

FILE: pyvex/utils.py
  function stable_hash (line 14) | def stable_hash(t: tuple) -> int:
  function _dump_tuple (line 20) | def _dump_tuple(t: tuple) -> bytes:
  function _dump_str (line 33) | def _dump_str(t: str) -> bytes:
  function _dump_int (line 37) | def _dump_int(t: int) -> bytes:
  function _dump_type (line 54) | def _dump_type(t: type) -> bytes:

FILE: pyvex_c/analysis.c
  function remove_noops (line 16) | void remove_noops(
  function get_exits_and_inst_addrs (line 38) | void get_exits_and_inst_addrs(
  function get_default_exit_target (line 72) | void get_default_exit_target(
  function Addr (line 184) | Addr get_value_from_const_expr(
  type HashHW (line 209) | typedef
  function HashHW (line 219) | static HashHW* newHHW()
  function freeHHW (line 230) | static void freeHHW(HashHW* h)
  function Bool (line 241) | static Bool lookupHHW(HashHW* h, /*OUT*/HWord* val, HWord key)
  function addToHHW (line 258) | static void addToHHW(HashHW* h, HWord key, HWord val)
  function removeFromHHW (line 302) | static void removeFromHHW(HashHW* h, HWord key)
  function UInt (line 317) | static UInt mk_key_GetPut ( Int offset, IRType ty )
  function record_data_reference (line 326) | void record_data_reference(
  function Addr (line 345) | Addr get_const_and_record(
  function record_tmp_value (line 371) | void record_tmp_value(
  type TmpValue (line 387) | typedef struct {
  type Region (line 393) | typedef struct {
  function find_region (line 404) | static int find_region(ULong start)
  function Bool (line 426) | Bool register_readonly_region(ULong start, ULong size, unsigned char* co...
  function deregister_all_readonly_regions (line 470) | void deregister_all_readonly_regions()
  function Bool (line 476) | Bool load_value(ULong addr, int size, int endness, void *value) {
  type InitialReg (line 534) | typedef struct _InitialReg {
  function Bool (line 543) | Bool register_initial_register_value(UInt offset, UInt size, ULong value)
  function Bool (line 564) | Bool reset_initial_register_values()
  function execute_irsb (line 571) | void execute_irsb(
  function get_is_noop_block (line 930) | void get_is_noop_block(

FILE: pyvex_c/e4c_lite.h
  type e4c_exception_type (line 33) | struct e4c_exception_type{
  type e4c_exception (line 48) | struct e4c_exception{
  type e4c_stage (line 72) | enum e4c_stage{e4c_beginning, e4c_trying, e4c_catching, e4c_finalizing, ...
  type e4c_context (line 73) | struct e4c_context{jmp_buf jump[E4C_MAX_FRAMES]; struct e4c_exception er...
  type e4c_exception_type (line 76) | struct e4c_exception_type
  type e4c_exception_type (line 76) | struct e4c_exception_type
  type e4c_exception_type (line 77) | struct e4c_exception_type

FILE: pyvex_c/logging.c
  function pyvex_debug (line 11) | void pyvex_debug(const char *fmt, ...)
  function pyvex_info (line 24) | void pyvex_info(const char *fmt, ...)
  function pyvex_error (line 37) | void pyvex_error(const char *fmt, ...)

FILE: pyvex_c/postprocess.c
  function arm_post_processor_determine_calls (line 27) | void arm_post_processor_determine_calls(
  function mips32_post_processor_fix_unconditional_exit (line 270) | void mips32_post_processor_fix_unconditional_exit(
  function irsb_insert (line 318) | void irsb_insert(IRSB *irsb, IRStmt* stmt, Int i) {
  function zero_division_side_exits (line 328) | void zero_division_side_exits(IRSB *irsb) {

FILE: pyvex_c/pyvex.c
  function failure_exit (line 58) | __declspec(noreturn)
  function log_bytes (line 66) | static void log_bytes(const HChar* bytes, SizeT nbytes) {
  function clear_log (line 82) | void clear_log() {
  function Bool (line 91) | static Bool chase_into_ok(void *closureV, Addr addr64) {
  function UInt (line 95) | static UInt needs_self_check(void *callback_opaque, VexRegisterUpdates* ...
  function vex_init (line 108) | int vex_init() {
  function vex_prepare_vai (line 225) | static void vex_prepare_vai(VexArch arch, VexArchInfo *vai) {
  function vex_prepare_vbi (line 289) | static void vex_prepare_vbi(VexArch arch, VexAbiInfo *vbi) {
  function VEXLiftResult (line 313) | VEXLiftResult *vex_lift(

FILE: pyvex_c/pyvex.h
  type ExitInfo (line 22) | typedef struct _ExitInfo {
  type DataRefTypes (line 28) | typedef enum {
  type DataRef (line 35) | typedef struct _DataRef {
  type ConstVal (line 43) | typedef struct _ConstVal {
  type VEXLiftResult (line 53) | typedef struct _VEXLiftResult {

FILE: tests/test_arm_postprocess.py
  function test_arm_postprocess_call (line 7) | def test_arm_postprocess_call():
  function test_arm_postprocess_ret (line 333) | def test_arm_postprocess_ret():

FILE: tests/test_gym.py
  class Tests (line 7) | class Tests(unittest.TestCase):
    method test_x86_aam (line 8) | def test_x86_aam(self):
    method test_x86_aad (line 13) | def test_x86_aad(self):
    method test_x86_xgetbv (line 18) | def test_x86_xgetbv(self):
    method test_x86_rdmsr (line 23) | def test_x86_rdmsr(self):

FILE: tests/test_irsb_property_caching.py
  class TestCacheInvalidationOnExtend (line 7) | class TestCacheInvalidationOnExtend(unittest.TestCase):
    method test_cache_invalidation_on_extend (line 8) | def test_cache_invalidation_on_extend(self):

FILE: tests/test_lift.py
  class TestLift (line 11) | class TestLift(unittest.TestCase):
    method test_partial_lift (line 12) | def test_partial_lift(self):
    method test_skipstmts_toomanyexits (line 34) | def test_skipstmts_toomanyexits(self):
    method test_max_bytes (line 69) | def test_max_bytes(self):

FILE: tests/test_mips32_postprocess.py
  function test_mips32_unconditional_jumps (line 4) | def test_mips32_unconditional_jumps():

FILE: tests/test_pyvex.py
  class TestPyvex (line 17) | class TestPyvex(unittest.TestCase):
    method test_memory (line 21) | def test_memory(self):
    method test_ircallee (line 63) | def test_ircallee(self):
    method test_irsb_empty (line 73) | def test_irsb_empty(self):
    method test_irsb_arm (line 77) | def test_irsb_arm(self):
    method test_irsb_popret (line 81) | def test_irsb_popret(self):
    method test_two_irsb (line 97) | def test_two_irsb(self):
    method test_irsb_deepCopy (line 106) | def test_irsb_deepCopy(self):
    method test_irsb_addStmt (line 114) | def test_irsb_addStmt(self):
    method test_irsb_tyenv (line 128) | def test_irsb_tyenv(self):
    method test_irstmt_pp (line 146) | def test_irstmt_pp(self):
    method test_irstmt_flat (line 153) | def test_irstmt_flat(self):
    method test_irstmt_imark (line 156) | def test_irstmt_imark(self):
    method test_irstmt_abihint (line 172) | def test_irstmt_abihint(self):
    method test_irstmt_put (line 183) | def test_irstmt_put(self):
    method test_irexpr_puti (line 194) | def test_irexpr_puti(self):
    method test_irstmt_wrtmp (line 206) | def test_irstmt_wrtmp(self):
    method test_irstmt_store (line 215) | def test_irstmt_store(self):
    method test_irstmt_cas (line 226) | def test_irstmt_cas(self):
    method test_irstmt_loadg (line 257) | def test_irstmt_loadg(self):
    method test_irstmt_storeg (line 284) | def test_irstmt_storeg(self):
    method test_irstmt_llsc (line 300) | def test_irstmt_llsc(self):
    method test_irstmt_mbe (line 312) | def test_irstmt_mbe(self):
    method test_irstmt_dirty (line 318) | def test_irstmt_dirty(self):
    method test_irstmt_exit (line 330) | def test_irstmt_exit(self):
    method test_irregarray (line 347) | def test_irregarray(self):
    method helper_const_subtype (line 358) | def helper_const_subtype(self, subtype, tag, value):
    method test_irconst (line 377) | def test_irconst(self):
    method test_irexpr_binder (line 394) | def test_irexpr_binder(self):
    method test_irexpr_geti (line 401) | def test_irexpr_geti(self):
    method test_irexpr_rdtmp (line 411) | def test_irexpr_rdtmp(self):
    method test_irexpr_get (line 419) | def test_irexpr_get(self):
    method test_irexpr_qop (line 425) | def test_irexpr_qop(self):
    method test_irexpr_triop (line 440) | def test_irexpr_triop(self):
    method test_irexpr_binop (line 454) | def test_irexpr_binop(self):
    method test_irexpr_unop (line 467) | def test_irexpr_unop(self):
    method test_irexpr_load (line 477) | def test_irexpr_load(self):
    method test_irexpr_const (line 487) | def test_irexpr_const(self):
    method test_irexpr_ite (line 497) | def test_irexpr_ite(self):
    method test_irexpr_ccall (line 506) | def test_irexpr_ccall(self):

FILE: tests/test_s390x_exrl.py
  function test_s390x_exrl (line 4) | def test_s390x_exrl():

FILE: tests/test_s390x_lochi.py
  function test_s390x_lochi (line 4) | def test_s390x_lochi():

FILE: tests/test_s390x_vl.py
  function test_s390x_vl (line 5) | def test_s390x_vl():

FILE: tests/test_spotter.py
  class Instruction_IMAGINARY (line 11) | class Instruction_IMAGINARY(Instruction):
    method compute_result (line 15) | def compute_result(self):
  class ImaginarySpotter (line 21) | class ImaginarySpotter(GymratLifter):
  function test_basic (line 38) | def test_basic():
  function test_embedded (line 43) | def test_embedded():
  class Instruction_MSR (line 61) | class Instruction_MSR(Instruction):
    method compute_result (line 65) | def compute_result(self):
  class Instruction_CPSIEI (line 71) | class Instruction_CPSIEI(Instruction):
    method compute_result (line 75) | def compute_result(self):
  class Instruction_CPSIEF (line 81) | class Instruction_CPSIEF(Instruction):
    method compute_result (line 85) | def compute_result(self):
  class CortexSpotter (line 91) | class CortexSpotter(GymratLifter):
  function test_tmrs (line 98) | def test_tmrs():
  function test_tmsr (line 108) | def test_tmsr():

FILE: tests/test_ud2.py
  function test_ud2 (line 4) | def test_ud2():
Condensed preview — 80 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (429K chars).
[
  {
    "path": ".git-blame-ignore-revs",
    "chars": 221,
    "preview": "# Black + pre-commit\n23503e79193a3cff5d6f1c92f22349fd2227d936 # Black\ncd758543f17a2253b5a0630327eac0ad6780217a # Trailin"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "chars": 2218,
    "preview": "name: Report a bug\ndescription: Report a bug in pyvex\nlabels: [bug,needs-triage]\nbody:\n  - type: markdown\n    attributes"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 205,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Join our Slack community\n    url: https://angr.io/invite/\n    about"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "chars": 1714,
    "preview": "name: Request a feature\ndescription: Request a new feature for pyvex\nlabels: [enhancement,needs-triage]\nbody:\n  - type: "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.yml",
    "chars": 1292,
    "preview": "name: Ask a question\ndescription: Ask a question about pyvex\nlabels: [question,needs-triage]\nbody:\n  - type: markdown\n  "
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 877,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n  workflow_dispatch:\n\njobs:\n  ecosystem:\n    uses: an"
  },
  {
    "path": ".github/workflows/cifuzz.yml",
    "chars": 1074,
    "preview": "name: OSS-Fuzz\n\non:\n  # push:\n  #   branches:\n  #     - master\n  # pull_request:\n  workflow_dispatch:\n\npermissions: {}\n\n"
  },
  {
    "path": ".github/workflows/nightly-ci.yml",
    "chars": 205,
    "preview": "name: Nightly CI\n\non:\n  schedule:\n  - cron: \"0 0 * * *\"\n  workflow_dispatch:\n\njobs:\n  ci:\n    uses: angr/ci-settings/.gi"
  },
  {
    "path": ".gitignore",
    "chars": 212,
    "preview": "build\ndist\nMANIFEST\npyvex_python\nvex_ffi.py\nlibpyvex.so\n*.egg-info\n*.eggs\n*.pyc\n*.swp\n*.obj\n*.lib\n*.dll\n*.exp\n*.o\n*.a\n*."
  },
  {
    "path": ".gitmodules",
    "chars": 86,
    "preview": "[submodule \"vex\"]\n\tpath = vex\n\turl = https://github.com/angr/vex.git\n\tbranch = master\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 2002,
    "preview": "repos:\n\n#\n# Fail fast\n#\n\n-   repo: https://github.com/abravalheri/validate-pyproject\n    rev: v0.25\n    hooks:\n    - id:"
  },
  {
    "path": ".readthedocs.yml",
    "chars": 451,
    "preview": "# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\nversion:"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 5157,
    "preview": "cmake_minimum_required(VERSION 3.15)\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\n\nproject(pyvex LANGUAGES C)\n\n# Set the outp"
  },
  {
    "path": "LICENSE",
    "chars": 1327,
    "preview": "Copyright (c) 2015, The Regents of the University of California\nAll rights reserved.\n\nRedistribution and use in source a"
  },
  {
    "path": "MANIFEST.in",
    "chars": 149,
    "preview": "include LICENSE\ninclude README.md\ninclude make_ffi.py\nrecursive-include pyvex_c *.c *.h *.def Makefile Makefile-msvc LIC"
  },
  {
    "path": "README.md",
    "chars": 8957,
    "preview": "# PyVEX\n[![Latest Release](https://img.shields.io/pypi/v/pyvex.svg)](https://pypi.python.org/pypi/pyvex/)\n[![Python Vers"
  },
  {
    "path": "docs/Makefile",
    "chars": 634,
    "preview": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the "
  },
  {
    "path": "docs/api.rst",
    "chars": 1058,
    "preview": ":mod:`pyvex` --- Binary Translator\n==================================\n\n.. automodule:: pyvex\n.. automodule:: pyvex.nativ"
  },
  {
    "path": "docs/conf.py",
    "chars": 1829,
    "preview": "# Configuration file for the Sphinx documentation builder.\n#\n# For the full list of built-in configuration values, see t"
  },
  {
    "path": "docs/index.rst",
    "chars": 257,
    "preview": "Welcome to pyVEX's documentation!\n=================================\n\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Contents"
  },
  {
    "path": "docs/make.bat",
    "chars": 765,
    "preview": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-bu"
  },
  {
    "path": "docs/quickstart.rst",
    "chars": 58,
    "preview": ".. include:: ../README.md\n   :parser: myst_parser.sphinx_\n"
  },
  {
    "path": "fuzzing/build.sh",
    "chars": 1389,
    "preview": "#!/bin/bash -eu\n# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you ma"
  },
  {
    "path": "fuzzing/enhanced_fdp.py",
    "chars": 2028,
    "preview": "# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
  },
  {
    "path": "fuzzing/irsb_fuzzer.py",
    "chars": 2964,
    "preview": "#!/usr/bin/python3\n# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you"
  },
  {
    "path": "make_ffi.py",
    "chars": 5136,
    "preview": "import logging\nimport os\nimport platform\nimport re\nimport subprocess\nimport sys\n\nimport cffi\n\nlog = logging.getLogger(\"c"
  },
  {
    "path": "pyproject.toml",
    "chars": 1715,
    "preview": "[build-system]\nrequires = [\"scikit-build-core >= 0.11.4, < 0.12.0\", \"cffi >= 1.0.3;implementation_name == 'cpython'\"]\nbu"
  },
  {
    "path": "pyvex/__init__.py",
    "chars": 1859,
    "preview": "\"\"\"\nPyVEX provides an interface that translates binary code into the VEX intermediate representation (IR).\nFor an introd"
  },
  {
    "path": "pyvex/_register_info.py",
    "chars": 49630,
    "preview": "REGISTER_OFFSETS = {\n    (\"x86\", \"eax\"): 8,\n    (\"x86\", \"ax\"): 8,\n    (\"x86\", \"al\"): 8,\n    (\"x86\", \"ah\"): 9,\n    (\"x86\""
  },
  {
    "path": "pyvex/arches.py",
    "chars": 3657,
    "preview": "from ._register_info import REGISTER_OFFSETS\nfrom .enums import default_vex_archinfo, vex_endness_from_string\nfrom .type"
  },
  {
    "path": "pyvex/block.py",
    "chars": 25391,
    "preview": "import copy\nimport itertools\nimport logging\nfrom typing import Optional\n\nfrom . import expr, stmt\nfrom .const import U1,"
  },
  {
    "path": "pyvex/const.py",
    "chars": 9484,
    "preview": "# pylint:disable=missing-class-docstring,raise-missing-from,not-callable\nimport re\nfrom abc import ABC\n\nfrom .enums impo"
  },
  {
    "path": "pyvex/const_val.py",
    "chars": 726,
    "preview": "class ConstVal:\n    \"\"\"\n    A constant value object. Indicates a constant value assignment to a VEX tmp variable.\n\n    :"
  },
  {
    "path": "pyvex/data_ref.py",
    "chars": 1733,
    "preview": "def data_ref_type_str(dref_enum):\n    \"\"\"\n    Translate an ``enum DataRefTypes`` value into a string representation.\n   "
  },
  {
    "path": "pyvex/enums.py",
    "chars": 4475,
    "preview": "from typing import Any\n\nfrom .native import ffi, pvc\nfrom .utils import stable_hash\n\n\nclass VEXObject:\n    \"\"\"\n    The b"
  },
  {
    "path": "pyvex/errors.py",
    "chars": 1191,
    "preview": "class PyVEXError(Exception):\n    pass\n\n\nclass SkipStatementsError(PyVEXError):\n    pass\n\n\n#\n# Exceptions and notificatio"
  },
  {
    "path": "pyvex/expr.py",
    "chars": 25860,
    "preview": "from __future__ import annotations\n\nimport logging\nimport re\nfrom typing import TYPE_CHECKING\n\nfrom .const import U8, U1"
  },
  {
    "path": "pyvex/lifting/__init__.py",
    "chars": 689,
    "preview": "from .gym import AARCH64Spotter, AMD64Spotter, ARMSpotter, X86Spotter\nfrom .libvex import LIBVEX_SUPPORTED_ARCHES, LibVE"
  },
  {
    "path": "pyvex/lifting/gym/README.md",
    "chars": 220,
    "preview": "# The Gym\n\nThis is where we're putting non-libvex lifters that we feel should be included with the pyvex distribution.\n\n"
  },
  {
    "path": "pyvex/lifting/gym/__init__.py",
    "chars": 204,
    "preview": "from .aarch64_spotter import AARCH64Spotter\nfrom .arm_spotter import ARMSpotter\nfrom .x86_spotter import AMD64Spotter, X"
  },
  {
    "path": "pyvex/lifting/gym/aarch64_spotter.py",
    "chars": 1220,
    "preview": "import logging\n\nfrom pyvex.lifting.util.instr_helper import Instruction\nfrom pyvex.lifting.util.lifter_helper import Gym"
  },
  {
    "path": "pyvex/lifting/gym/arm_spotter.py",
    "chars": 15053,
    "preview": "import logging\n\nimport bitstring\n\nfrom pyvex.lifting.util import JumpKind, Type\nfrom pyvex.lifting.util.instr_helper imp"
  },
  {
    "path": "pyvex/lifting/gym/x86_spotter.py",
    "chars": 4067,
    "preview": "import logging\n\nfrom pyvex.lifting.util import GymratLifter, Instruction, JumpKind, Type\n\nlog = logging.getLogger(__name"
  },
  {
    "path": "pyvex/lifting/libvex.py",
    "chars": 3560,
    "preview": "import logging\nimport threading\nfrom typing import TYPE_CHECKING\n\nfrom pyvex.errors import LiftingException\nfrom pyvex.n"
  },
  {
    "path": "pyvex/lifting/lift_function.py",
    "chars": 13172,
    "preview": "import logging\nfrom collections import defaultdict\nfrom typing import DefaultDict\n\nfrom pyvex import const\nfrom pyvex.bl"
  },
  {
    "path": "pyvex/lifting/lifter.py",
    "chars": 5808,
    "preview": "from pyvex.block import IRSB\nfrom pyvex.types import Arch, LiftSource\n\n# pylint:disable=attribute-defined-outside-init\n\n"
  },
  {
    "path": "pyvex/lifting/post_processor.py",
    "chars": 289,
    "preview": "#\n# The post-processor base class\n#\n\n\nclass Postprocessor:\n    def __init__(self, irsb):\n        self.irsb = irsb\n\n    d"
  },
  {
    "path": "pyvex/lifting/util/__init__.py",
    "chars": 300,
    "preview": "from .instr_helper import Instruction\nfrom .lifter_helper import GymratLifter, ParseError\nfrom .syntax_wrapper import Ve"
  },
  {
    "path": "pyvex/lifting/util/instr_helper.py",
    "chars": 17888,
    "preview": "import abc\nimport string\n\nimport bitstring\n\nfrom pyvex.expr import IRExpr, RdTmp\n\nfrom .lifter_helper import ParseError\n"
  },
  {
    "path": "pyvex/lifting/util/lifter_helper.py",
    "chars": 5309,
    "preview": "import logging\nfrom typing import TYPE_CHECKING\n\nimport bitstring\n\nfrom pyvex.const import vex_int_class\nfrom pyvex.erro"
  },
  {
    "path": "pyvex/lifting/util/syntax_wrapper.py",
    "chars": 8842,
    "preview": "import functools\nfrom typing import Union\n\nfrom pyvex.const import get_type_size\nfrom pyvex.expr import Const, IRExpr, R"
  },
  {
    "path": "pyvex/lifting/util/vex_helper.py",
    "chars": 10080,
    "preview": "import copy\nimport re\n\nfrom pyvex.const import U1, get_type_size, ty_to_const_class, vex_int_class\nfrom pyvex.enums impo"
  },
  {
    "path": "pyvex/lifting/zerodivision.py",
    "chars": 2580,
    "preview": "import copy\n\nfrom pyvex import const, expr, stmt\n\nfrom .post_processor import Postprocessor\n\n\nclass ZeroDivisionPostProc"
  },
  {
    "path": "pyvex/native.py",
    "chars": 1867,
    "preview": "import getpass\nimport hashlib\nimport importlib.resources\nimport os\nimport pickle\nimport sys\nimport tempfile\nfrom typing "
  },
  {
    "path": "pyvex/py.typed",
    "chars": 8,
    "preview": "partial\n"
  },
  {
    "path": "pyvex/stmt.py",
    "chars": 22290,
    "preview": "from __future__ import annotations\n\nimport logging\nfrom collections.abc import Iterator\nfrom typing import TYPE_CHECKING"
  },
  {
    "path": "pyvex/types.py",
    "chars": 1005,
    "preview": "from typing import TYPE_CHECKING, Any, Protocol, Union, runtime_checkable\n\nfrom cffi.api import FFI\n\n\nclass Register(Pro"
  },
  {
    "path": "pyvex/utils.py",
    "chars": 1429,
    "preview": "import struct\nfrom collections.abc import Callable\nfrom typing import Any\n\ntry:\n    import _md5 as md5lib\nexcept ImportE"
  },
  {
    "path": "pyvex_c/LICENSE",
    "chars": 18092,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
  },
  {
    "path": "pyvex_c/README",
    "chars": 288,
    "preview": "To generate the list of exports for windows:\n\ngrep -E -o -h -r \"pvc\\.[a-zA-Z0-9_]+\" | cut -c 5- | sort -u\n\nThen remove I"
  },
  {
    "path": "pyvex_c/analysis.c",
    "chars": 26489,
    "preview": "#include <libvex.h>\n#include <stddef.h>\n#include <assert.h>\n#include <stdlib.h>\n#include <string.h>\n#include <libvex_gue"
  },
  {
    "path": "pyvex_c/e4c_lite.h",
    "chars": 2765,
    "preview": "/*\n * exceptions4c lightweight version 1.0\n *\n * Copyright (c) 2014 Guillermo Calvo\n * Licensed under the GNU Lesser Gen"
  },
  {
    "path": "pyvex_c/logging.c",
    "chars": 794,
    "preview": "// This code is GPLed by Yan Shoshitaishvili\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n\n#include \"logg"
  },
  {
    "path": "pyvex_c/logging.h",
    "chars": 226,
    "preview": "// This code is GPLed by Yan Shoshitaishvili\n\n#ifndef __COMMON_H\n#define __COMMON_H\n\nextern int log_level;\n\nvoid pyvex_d"
  },
  {
    "path": "pyvex_c/postprocess.c",
    "chars": 12098,
    "preview": "#include <libvex.h>\n#include <libvex_guest_arm.h>\n#include <stddef.h>\n\n#include \"pyvex_internal.h\"\n\n//\n// Jumpkind fixes"
  },
  {
    "path": "pyvex_c/pyvex.c",
    "chars": 11136,
    "preview": "/*\nThis is shamelessly ripped from Vine, because those guys have very very strange language preferences.\nVine is Copyrig"
  },
  {
    "path": "pyvex_c/pyvex.def",
    "chars": 923,
    "preview": "LIBRARY pyvex.dll\r\n\r\nEXPORTS\r\n  IRConst_F32\r\n  IRConst_F32i\r\n  IRConst_F64\r\n  IRConst_F64i\r\n  IRConst_U1\r\n  IRConst_U16\r"
  },
  {
    "path": "pyvex_c/pyvex.h",
    "chars": 1962,
    "preview": "// This code is GPLed by Yan Shoshitaishvili\n\n#ifndef __VEXIR_H\n#define __VEXIR_H\n\n#include <libvex.h>\n\n// Some info req"
  },
  {
    "path": "pyvex_c/pyvex_internal.h",
    "chars": 631,
    "preview": "#include \"pyvex.h\"\n\nvoid arm_post_processor_determine_calls(Addr irsb_addr, Int irsb_size, Int irsb_insts, IRSB *irsb);\n"
  },
  {
    "path": "tests/test_arm_postprocess.py",
    "chars": 10296,
    "preview": "import pyvex\n\n\n##########################\n### ARM Postprocessing ###\n##########################\ndef test_arm_postprocess"
  },
  {
    "path": "tests/test_gym.py",
    "chars": 883,
    "preview": "# pylint: disable=missing-class-docstring\nimport unittest\n\nimport pyvex\n\n\nclass Tests(unittest.TestCase):\n    def test_x"
  },
  {
    "path": "tests/test_irsb_property_caching.py",
    "chars": 728,
    "preview": "# pylint: disable=missing-class-docstring,no-self-use\nimport unittest\n\nimport pyvex\n\n\nclass TestCacheInvalidationOnExten"
  },
  {
    "path": "tests/test_lift.py",
    "chars": 3263,
    "preview": "import unittest\n\nimport pyvex\nfrom pyvex import IRSB, ffi, lift\nfrom pyvex.errors import PyVEXError\nfrom pyvex.lifting.u"
  },
  {
    "path": "tests/test_mips32_postprocess.py",
    "chars": 638,
    "preview": "import pyvex\n\n\ndef test_mips32_unconditional_jumps():\n    # 0040000c: 10000002 ; <input:28> beq $zero, $zero, LABEL_ELSE"
  },
  {
    "path": "tests/test_pyvex.py",
    "chars": 15885,
    "preview": "import copy\nimport gc\nimport logging\nimport os\nimport random\nimport sys\nimport unittest\n\nimport pyvex\nfrom pyvex.lifting"
  },
  {
    "path": "tests/test_s390x_exrl.py",
    "chars": 694,
    "preview": "import pyvex\n\n\ndef test_s390x_exrl():\n    arch = pyvex.ARCH_S390X\n    irsb = pyvex.lift(\n        b\"\\xc6\\x10\\x00\\x00\\x00\\"
  },
  {
    "path": "tests/test_s390x_lochi.py",
    "chars": 388,
    "preview": "import pyvex\n\n\ndef test_s390x_lochi():\n    arch = pyvex.ARCH_S390X\n    irsb = pyvex.lift(b\"\\xec\\x18\\xab\\xcd\\x00\\x42\", 0x"
  },
  {
    "path": "tests/test_s390x_vl.py",
    "chars": 449,
    "preview": "#!/usr/bin/env python3\nimport pyvex\n\n\ndef test_s390x_vl():\n    arch = pyvex.ARCH_S390X\n    irsb = pyvex.lift(b\"\\xe7\\x40\\"
  },
  {
    "path": "tests/test_spotter.py",
    "chars": 3383,
    "preview": "import os\n\nimport pyvex\nimport pyvex.lifting\nfrom pyvex.lifting import register\nfrom pyvex.lifting.util import GymratLif"
  },
  {
    "path": "tests/test_ud2.py",
    "chars": 507,
    "preview": "import pyvex\n\n\ndef test_ud2():\n    # On x86 and amd64, ud2 is a valid 2-byte instruction that means \"undefined instructi"
  }
]

About this extraction

This page contains the full source code of the angr/pyvex GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 80 files (387.1 KB), approximately 119.8k tokens, and a symbol index with 738 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!