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
[](https://pypi.python.org/pypi/pyvex/)
[](https://pypi.python.org/pypi/pyvex/)
[](https://pypistats.org/packages/pyvex)
[](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
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
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[](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.