mirror of
https://github.com/bitdefender/bddisasm.git
synced 2024-12-22 05:58:07 +00:00
BDDISASM v2.1.0 release - please consult the CHANGELOG for details about the modifications.
This commit is contained in:
parent
727c87ecc4
commit
fad9c7e35c
8
.gitignore
vendored
8
.gitignore
vendored
@ -57,7 +57,9 @@ compile_commands.json
|
|||||||
pydis/.eggs
|
pydis/.eggs
|
||||||
bdshemu_fuzz/out
|
bdshemu_fuzz/out
|
||||||
bdshemu_fuzz/shfuzz
|
bdshemu_fuzz/shfuzz
|
||||||
|
bdshemu_fuzz/in-32
|
||||||
bdshemu_fuzz/out-32
|
bdshemu_fuzz/out-32
|
||||||
|
bdshemu_fuzz/in-64
|
||||||
bdshemu_fuzz/out-64
|
bdshemu_fuzz/out-64
|
||||||
docs/build
|
docs/build
|
||||||
libbddisasm.pc
|
libbddisasm.pc
|
||||||
@ -67,3 +69,9 @@ disasmtool_lix/_build
|
|||||||
bindings/rsbddisasm/target
|
bindings/rsbddisasm/target
|
||||||
bindings/rsbddisasm/Cargo.lock
|
bindings/rsbddisasm/Cargo.lock
|
||||||
bindings/pybddisasm/pybddisasm.egg-info
|
bindings/pybddisasm/pybddisasm.egg-info
|
||||||
|
bindings/rsbddisasm/bddisasm/target
|
||||||
|
bindings/pybddisasm/pybddisasm/pybddisasm.py
|
||||||
|
bindings/pybddisasm/pybddisasm/pybddisasm_wrap.c
|
||||||
|
|
||||||
|
bddfuzz.tar
|
||||||
|
bindings/pybddisasm/.eggs
|
||||||
|
54
CHANGELOG.md
Normal file
54
CHANGELOG.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable (user-facing) changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.1.0] - 2024-02-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Support in bddisasm for Intel REX2 prefix.
|
||||||
|
- Support in bddisasm for Intel APX extensions.
|
||||||
|
- Support in bddisasm for Intel USERMSR extensions.
|
||||||
|
- Support in bddisasm for prefix activation fields inside `INSTRUX` - these fields can be consulted to determine whether a particular prefix is present, accepted & active.
|
||||||
|
- New feature in bdshemu: `SHEMU_OPT_DIRECT_MAPPED_SHELL` - allows emulation with a smaller `IntBuff` at the cost of not having `WRITE_SELF` detections. The shellcode can be provided directly from its original location, without the need to allocate it in a dedicated memory region.
|
||||||
|
- New feature in bdshemu: `SHEMU_OPT_TRACK_LOOPS` - loops can now be tracked by bdshemu. `SHEMU_OPT_TRACE_LOOPS` can be used to log loop information.
|
||||||
|
- Support in bdshemu for APX instructions (both REX2 and EVEX encoded instructions) - the new `SHEMU_OPT_SUPPORT_APX` must be set in order to enable APX emulation.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Reduced the size of the `INSTRUX` structure from 856 bytes to 488 bytes (almost -43%!).
|
||||||
|
- Increased decoding performance from average 300 clocks/instruction to average 235 clocks/instruction (almost +20%!).
|
||||||
|
- New decode options - do not decode implicit operands - this further increases performance from average 235 clocks/instruction to 200 clocks/instruction (almost +15%!).
|
||||||
|
- Re-worked the Python scripts - both `disasmlib.py` and `generate_tables.py` have been significantly reworked, improving readability, and making them more efficient.
|
||||||
|
- `disasmtool` builds on Linux.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Support for Cyrix & VIA instructions - only current Intel & AMD instructions remain supported.
|
||||||
|
- disasmtool_lix has been removed. `disasmtool` is available on Linux as well.
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
#### Inside INSTRUX
|
||||||
|
- Removed `Iclass` field - it was aliased over `Instruction` field, which must be used from now on.
|
||||||
|
- Removed `OperandsEncodingMap` field - one can consult the `Encoding` field in each operand to determine the encoding.
|
||||||
|
- Removed `ExceptionClass` field - only `ExceptionType` remains, which contains an enum with all the exception types.
|
||||||
|
- Removed `Predicate` field - only `Condition` remains, which was aliased over `Predicate`.
|
||||||
|
- Removed `HasImm3`, `Immediate3`, `Imm3Length` and `Imm3Offset` fields, as they were not used/needed.
|
||||||
|
- Removed `Bhint`, `SseCondition`, `SignDisp` fields, as they were not used.
|
||||||
|
- Moved `FlagsAccess.RegAccess` outside and renamed it to `RflAccess`, to save more space.
|
||||||
|
- Switched from `char Mnemonic[32]` to `const char *Mnemonic` - this decreases INSTRUX size by almost 32 bytes, and increases perf.
|
||||||
|
|
||||||
|
#### Inside ND_OPERAND
|
||||||
|
- Removed `RawSize` - in most cases, `Size` and `RawSize` are identical; the only case where they might differ is for `Immediate` and `RelativeOffset` operands - in that case, one can consult the `RawSize` field in `Immediate` or `RelativeOffset`.
|
||||||
|
|
||||||
|
#### Inside ND_OPERAND_DECORATOR
|
||||||
|
- Removed `Broadcast` field, moved it inside `ND_OPDESC_MEMORY`.
|
||||||
|
- Removed `HasSae`, `HasEr` - they are per instruction, not per operand, and can be consulted directly inside `INSTRUX`.
|
||||||
|
- Moved `Msk` one level up, inside the `ND_OPERAND_DECORATOR` structure.
|
||||||
|
|
||||||
|
#### Defines & constants
|
||||||
|
- Removed `ND_PRED_*` defines - search & replace them with `ND_COND_*`.
|
||||||
|
- Removed `ND_HAS_PREDICATE` - use `ND_HAS_CONDITION` instead.
|
||||||
|
- Removed `ND_VEND_GEODE` and `ND_VEND_CYRIX`.
|
@ -1,16 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
option(BDD_INCLUDE_TOOL "Include the disasmtool executable" ON)
|
option(BDD_INCLUDE_TOOL "Include the disasmtool executable" ON)
|
||||||
option(BDD_INCLUDE_ISAGENERATOR "Include the isagenerator target (if a python interpreter is found)" ON)
|
option(BDD_INCLUDE_ISAGENERATOR_X86 "Include the x86 isagenerator target (if a python interpreter is found)" ON)
|
||||||
option(BDD_INCLUDE_FUZZERS "Include the bdshemu fuzzer" OFF)
|
option(BDD_INCLUDE_FUZZERS "Include the bdshemu fuzzer" OFF)
|
||||||
option(BDD_USE_EXTERNAL_VSNPRINTF "Expect nd_vsnprintf_s implementation from the integrator" OFF)
|
option(BDD_USE_EXTERNAL_VSNPRINTF "Expect nd_vsnprintf_s implementation from the integrator" OFF)
|
||||||
option(BDD_USE_EXTERNAL_MEMSET "Expect nd_memset implementation from the integrator" OFF)
|
option(BDD_USE_EXTERNAL_MEMSET "Expect nd_memset implementation from the integrator" OFF)
|
||||||
|
option(BDD_ASAN "Build with ASAN" OFF)
|
||||||
|
option(BDD_UBSAN "Build with UBSAN" OFF)
|
||||||
|
|
||||||
set(BDD_VER_FILE ${CMAKE_CURRENT_LIST_DIR}/inc/version.h)
|
set(BDD_VER_FILE ${CMAKE_CURRENT_LIST_DIR}/inc/bddisasm_version.h)
|
||||||
|
|
||||||
file(STRINGS ${BDD_VER_FILE} disasm_ver_major REGEX "DISASM_VERSION_MAJOR")
|
file(STRINGS ${BDD_VER_FILE} disasm_ver_major REGEX "#define DISASM_VERSION_MAJOR")
|
||||||
file(STRINGS ${BDD_VER_FILE} disasm_ver_minor REGEX "DISASM_VERSION_MINOR")
|
file(STRINGS ${BDD_VER_FILE} disasm_ver_minor REGEX "#define DISASM_VERSION_MINOR")
|
||||||
file(STRINGS ${BDD_VER_FILE} disasm_ver_patch REGEX "DISASM_VERSION_REVISION")
|
file(STRINGS ${BDD_VER_FILE} disasm_ver_patch REGEX "#define DISASM_VERSION_REVISION")
|
||||||
|
|
||||||
string(REGEX REPLACE "#define DISASM_VERSION_MAJOR[ \t\r\n]*" "" disasm_ver_major ${disasm_ver_major})
|
string(REGEX REPLACE "#define DISASM_VERSION_MAJOR[ \t\r\n]*" "" disasm_ver_major ${disasm_ver_major})
|
||||||
string(REGEX REPLACE "#define DISASM_VERSION_MINOR[ \t\r\n]*" "" disasm_ver_minor ${disasm_ver_minor})
|
string(REGEX REPLACE "#define DISASM_VERSION_MINOR[ \t\r\n]*" "" disasm_ver_minor ${disasm_ver_minor})
|
||||||
@ -25,7 +27,7 @@ project(
|
|||||||
LANGUAGES C
|
LANGUAGES C
|
||||||
HOMEPAGE_URL https://github.com/bitdefender/bddisasm)
|
HOMEPAGE_URL https://github.com/bitdefender/bddisasm)
|
||||||
|
|
||||||
# Use Release as the build type if no build type was specified and we're not using a multi-config generator .
|
# Use Release as the build type if no build type was specified and we're not using a multi-config generator.
|
||||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
message(STATUS "No build type given. Will use 'Release'")
|
message(STATUS "No build type given. Will use 'Release'")
|
||||||
set(CMAKE_BUILD_TYPE
|
set(CMAKE_BUILD_TYPE
|
||||||
@ -79,12 +81,17 @@ endif ()
|
|||||||
|
|
||||||
set(BDDISASM_PUBLIC_HEADERS
|
set(BDDISASM_PUBLIC_HEADERS
|
||||||
"inc/bddisasm.h"
|
"inc/bddisasm.h"
|
||||||
"inc/constants.h"
|
"inc/bddisasm_status.h"
|
||||||
"inc/cpuidflags.h"
|
"inc/bddisasm_types.h"
|
||||||
"inc/disasmstatus.h"
|
"inc/bddisasm_version.h"
|
||||||
"inc/disasmtypes.h"
|
"inc/bdx86_constants.h"
|
||||||
"inc/registers.h"
|
"inc/bdx86_core.h"
|
||||||
"inc/version.h")
|
"inc/bdx86_cpuidflags.h"
|
||||||
|
"inc/bdx86_registers.h")
|
||||||
|
|
||||||
|
set(BDSHEMU_PUBLIC_HEADERS
|
||||||
|
"inc/bdshemu_x86.h"
|
||||||
|
"inc/bdshemu.h")
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
@ -100,20 +107,20 @@ include(CheckCCompilerFlag)
|
|||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
bddisasm STATIC
|
bddisasm STATIC
|
||||||
bddisasm/crt.c
|
bddisasm/bddisasm_crt.c
|
||||||
bddisasm/bddisasm.c
|
bddisasm/bdx86_decoder.c
|
||||||
bddisasm/bdformat.c
|
bddisasm/bdx86_formatter.c
|
||||||
bddisasm/bdhelpers.c
|
bddisasm/bdx86_helpers.c
|
||||||
# Add the headers so they will show up in IDEs.
|
# Add the headers so they will show up in IDEs.
|
||||||
bddisasm/include/instructions.h
|
bddisasm/include/bddisasm_crt.h
|
||||||
bddisasm/include/mnemonics.h
|
bddisasm/include/bdx86_instructions.h
|
||||||
bddisasm/include/nd_crt.h
|
bddisasm/include/bdx86_mnemonics.h
|
||||||
bddisasm/include/prefixes.h
|
bddisasm/include/bdx86_prefixes.h
|
||||||
bddisasm/include/table_evex.h
|
bddisasm/include/bdx86_tabledefs.h
|
||||||
bddisasm/include/table_root.h
|
bddisasm/include/bdx86_table_evex.h
|
||||||
bddisasm/include/table_vex.h
|
bddisasm/include/bdx86_table_root.h
|
||||||
bddisasm/include/table_xop.h
|
bddisasm/include/bdx86_table_vex.h
|
||||||
bddisasm/include/tabledefs.h
|
bddisasm/include/bdx86_table_xop.h
|
||||||
"${BDDISASM_PUBLIC_HEADERS}")
|
"${BDDISASM_PUBLIC_HEADERS}")
|
||||||
|
|
||||||
if (NOT BDD_USE_EXTERNAL_VSNPRINTF)
|
if (NOT BDD_USE_EXTERNAL_VSNPRINTF)
|
||||||
@ -154,6 +161,20 @@ set_target_properties(
|
|||||||
VERSION ${CMAKE_PROJECT_VERSION}
|
VERSION ${CMAKE_PROJECT_VERSION}
|
||||||
SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR})
|
SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR})
|
||||||
|
|
||||||
|
if (BDD_ASAN)
|
||||||
|
target_compile_options(bddisasm PUBLIC "-fsanitize=address")
|
||||||
|
target_link_libraries(bddisasm PUBLIC "-fsanitize=address")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (BDD_UBSAN)
|
||||||
|
target_compile_options(bddisasm PUBLIC
|
||||||
|
"-fsanitize=undefined"
|
||||||
|
"-fno-sanitize=alignment")
|
||||||
|
target_link_libraries(bddisasm PUBLIC
|
||||||
|
"-fsanitize=undefined"
|
||||||
|
"-fno-sanitize=alignment")
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_library(bddisasm::bddisasm ALIAS bddisasm)
|
add_library(bddisasm::bddisasm ALIAS bddisasm)
|
||||||
|
|
||||||
# -- bdshemu --
|
# -- bdshemu --
|
||||||
@ -161,8 +182,10 @@ add_library(bddisasm::bddisasm ALIAS bddisasm)
|
|||||||
add_library(
|
add_library(
|
||||||
bdshemu STATIC
|
bdshemu STATIC
|
||||||
bdshemu/bdshemu.c
|
bdshemu/bdshemu.c
|
||||||
|
bdshemu/bdshemu_x86.c
|
||||||
# Add the headers so they will show up in IDEs.
|
# Add the headers so they will show up in IDEs.
|
||||||
inc/bdshemu.h)
|
bdshemu/include/bdshemu_common.h
|
||||||
|
"${BDSHEMU_PUBLIC_HEADERS}")
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
bdshemu
|
bdshemu
|
||||||
@ -185,7 +208,7 @@ endif ()
|
|||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
bdshemu
|
bdshemu
|
||||||
PROPERTIES PUBLIC_HEADER "inc/bdshemu.h"
|
PROPERTIES PUBLIC_HEADER "${BDSHEMU_PUBLIC_HEADERS}"
|
||||||
VERSION ${CMAKE_PROJECT_VERSION}
|
VERSION ${CMAKE_PROJECT_VERSION}
|
||||||
SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR})
|
SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR})
|
||||||
|
|
||||||
@ -193,19 +216,14 @@ add_library(bddisasm::bdshemu ALIAS bdshemu)
|
|||||||
|
|
||||||
# If this is the master project (and if the user requested it) add disasmtool.
|
# If this is the master project (and if the user requested it) add disasmtool.
|
||||||
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_TOOL)
|
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_TOOL)
|
||||||
if (WIN32)
|
|
||||||
add_subdirectory(disasmtool)
|
add_subdirectory(disasmtool)
|
||||||
else ()
|
|
||||||
add_subdirectory(disasmtool_lix)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# If this is the master project (and if the user requested it) add isagenerator.
|
# If this is the master project (and if the user requested it) add isagenerator.
|
||||||
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_ISAGENERATOR)
|
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_ISAGENERATOR_X86)
|
||||||
add_subdirectory(isagenerator)
|
add_subdirectory(isagenerator)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# If this is the master project (and if the user requested it) add the fuzzer.
|
|
||||||
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_FUZZERS)
|
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_FUZZERS)
|
||||||
add_subdirectory(bdshemu_fuzz)
|
add_subdirectory(bdshemu_fuzz)
|
||||||
endif ()
|
endif ()
|
||||||
|
118
Dockerfile.fuzzing
Normal file
118
Dockerfile.fuzzing
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
FROM ubuntu:22.04 as build
|
||||||
|
|
||||||
|
WORKDIR /bddfuzz
|
||||||
|
|
||||||
|
# Install everything we need to build AFL++ and honggfuzz and bdshemu
|
||||||
|
# We install both clang-13 and clang-15 because honggfuzz does not support newer versions of clang, but AFL++ wants
|
||||||
|
# the latest version so it is what it is
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
cmake make git \
|
||||||
|
binutils-dev \
|
||||||
|
libunwind-dev \
|
||||||
|
libblocksruntime-dev \
|
||||||
|
clang-13 \
|
||||||
|
clang-15 \
|
||||||
|
llvm-15 llvm-15-dev llvm-15-linker-tools llvm-15-runtime llvm-15-tools lld-15
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN mkdir /bddfuzz/fuzzers
|
||||||
|
|
||||||
|
# Build and install AFL++
|
||||||
|
RUN cd /bddfuzz/fuzzers && git clone https://github.com/AFLplusplus/AFLplusplus.git
|
||||||
|
RUN cd /bddfuzz/fuzzers/AFLplusplus && \
|
||||||
|
CC=clang-15 CXX=clang++-15 make source-only install LLVM_CONFIG=llvm-config-15 NO_NYX=1
|
||||||
|
|
||||||
|
# Build and install honggfuzz
|
||||||
|
RUN cd /bddfuzz/fuzzers && git clone --depth 1 --branch 2.5 https://github.com/google/honggfuzz.git
|
||||||
|
RUN cd /bddfuzz/fuzzers/honggfuzz && make install
|
||||||
|
|
||||||
|
# Remove the fuzzer source files as we no longer need them
|
||||||
|
RUN cd /bddfuzz/fuzzers/AFLplusplus && git clean -dxf && git clean -dXf && rm -rf /bddfuzz/fuzzers/AFLplusplus
|
||||||
|
RUN rm -rf /bddfuzz/fuzzers/honggfuzz
|
||||||
|
RUN rm -rf /bddfuzz/fuzzers/
|
||||||
|
|
||||||
|
ENV SRC /bddfuzz/src/
|
||||||
|
|
||||||
|
# Copy the relevant bddisasm sources
|
||||||
|
RUN mkdir "${SRC}"
|
||||||
|
|
||||||
|
COPY CMakeLists.txt "${SRC}"/CMakeLists.txt
|
||||||
|
COPY bddisasm.pc.in "${SRC}"/bddisasm.pc.in
|
||||||
|
COPY bddisasmConfig.cmake "${SRC}"/bddisasmConfig.cmake
|
||||||
|
COPY bddisasm "${SRC}"/bddisasm
|
||||||
|
COPY bdshemu "${SRC}"/bdshemu
|
||||||
|
COPY bdshemu_fuzz "${SRC}"/bdshemu_fuzz
|
||||||
|
COPY inc "${SRC}"/inc
|
||||||
|
|
||||||
|
# Now build all the variants
|
||||||
|
RUN mkdir build
|
||||||
|
|
||||||
|
# Build for AFL++ with afl-clang-lto
|
||||||
|
RUN mkdir /bddfuzz/build/afllto && cd /bddfuzz/build/afllto && \
|
||||||
|
cmake "${SRC}" -DCMAKE_C_COMPILER=afl-clang-lto -DCMAKE_CXX_COMPILER=afl-clang-lto++ \
|
||||||
|
-DCMAKE_BUILD_TYPE=Releaase \
|
||||||
|
-DBDD_INCLUDE_TOOL=OFF -DBDD_INCLUDE_ISAGENERATOR_X86=OFF \
|
||||||
|
-DBDD_INCLUDE_FUZZERS=ON && \
|
||||||
|
make shfuzz
|
||||||
|
|
||||||
|
# Build for honggfuzz
|
||||||
|
RUN mkdir /bddfuzz/build/hfuzz && cd /bddfuzz/build/hfuzz && \
|
||||||
|
cmake "${SRC}" -DCMAKE_C_COMPILER=hfuzz-clang -DCMAKE_CXX_COMPILER=hfuzz-clang++ \
|
||||||
|
-DCMAKE_BUILD_TYPE=Releaase \
|
||||||
|
-DBDD_INCLUDE_TOOL=OFF -DBDD_INCLUDE_ISAGENERATOR_X86=OFF \
|
||||||
|
-DBDD_INCLUDE_FUZZERS=ON && \
|
||||||
|
make shfuzz
|
||||||
|
|
||||||
|
# Build for libfuzzer with ASAN and UBSAN
|
||||||
|
RUN mkdir /bddfuzz/build/san && cd /bddfuzz/build/san && \
|
||||||
|
cmake "${SRC}" -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang-15++ \
|
||||||
|
-DCMAKE_BUILD_TYPE=Releaase \
|
||||||
|
-DBDD_INCLUDE_TOOL=OFF -DBDD_INCLUDE_ISAGENERATOR_X86=OFF \
|
||||||
|
-DBDD_INCLUDE_FUZZERS=ON -DBDD_FUZZ_WITH_LOGS=ON \
|
||||||
|
-DBDD_ASAN=ON -DBDD_UBSAN=ON && \
|
||||||
|
make shfuzz
|
||||||
|
|
||||||
|
RUN rm -rf "${SRC}"
|
||||||
|
|
||||||
|
# Save the fuzzers
|
||||||
|
RUN mkdir /bddfuzz/shf && cd /bddfuzz/shf && \
|
||||||
|
for d in /bddfuzz/build/*; do \
|
||||||
|
mkdir ./`basename "${d}"` && \
|
||||||
|
cp -v "${d}"/bdshemu_fuzz/shfuzz* ./`basename "${d}"`; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove the build directory
|
||||||
|
RUN rm -rf build
|
||||||
|
|
||||||
|
FROM ubuntu:22.04 as run
|
||||||
|
|
||||||
|
WORKDIR /bddfuzz
|
||||||
|
|
||||||
|
# Copy the fuzzers from the build stage
|
||||||
|
COPY --from=build /bddfuzz/shf /bddfuzz/shf
|
||||||
|
|
||||||
|
# Copy AFL++ and honggfuzz binaries
|
||||||
|
COPY --from=build /usr/local/bin/afl-* /usr/local/bin/
|
||||||
|
COPY --from=build /usr/local/bin/hfuzz-* /usr/local/bin/
|
||||||
|
COPY --from=build /usr/local/bin/honggfuzz /usr/local/bin/
|
||||||
|
|
||||||
|
RUN mkdir /bddfuzz/inputs
|
||||||
|
COPY bdshemu_fuzz/in-32 /bddfuzz/inputs/in-32
|
||||||
|
COPY bdshemu_fuzz/in-64 /bddfuzz/inputs/in-64
|
||||||
|
|
||||||
|
# Runtime dependencies for honggfuzz
|
||||||
|
RUN apt-get update && apt-get install -y binutils-dev libunwind-dev libblocksruntime-dev
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# So we can share files between the host and the container (we don't want to loose the results when we stop the
|
||||||
|
# container).
|
||||||
|
ENV SHARE_DIR share
|
||||||
|
|
||||||
|
COPY bdshemu_fuzz/fuzzing_image_entrypoint.sh /bddfuzz/fuzzing_image_entrypoint.sh
|
||||||
|
RUN chmod +x /bddfuzz/fuzzing_image_entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/bddfuzz/fuzzing_image_entrypoint.sh"]
|
10
README.md
10
README.md
@ -5,12 +5,10 @@ The Bitdefender disassembler (bddisasm) is a lightweight, x86/x64 only instructi
|
|||||||
## Projects
|
## Projects
|
||||||
|
|
||||||
1. [bddisasm](https://github.com/bitdefender/bddisasm/tree/master/bddisasm) - this is the main disassembler project. In order to use the Bitdefender disassembler, all you have to do is build this project, and link with the output library. The only headers you need are located inside the `inc` folder.
|
1. [bddisasm](https://github.com/bitdefender/bddisasm/tree/master/bddisasm) - this is the main disassembler project. In order to use the Bitdefender disassembler, all you have to do is build this project, and link with the output library. The only headers you need are located inside the `inc` folder.
|
||||||
2. [bdshemu](https://github.com/bitdefender/bddisasm/tree/master/bdshemu) - this project makes use of the main bddisasm lib in order to build a simple, lightweight, fast, instructions emulator, designated to target shellcodes. This project is also integrated inside the disasmtool, so you can
|
2. [bdshemu](https://github.com/bitdefender/bddisasm/tree/master/bdshemu) - this project makes use of the main bddisasm lib in order to build a simple, lightweight, fast, instructions emulator, designated to target shellcodes. This project is also integrated inside the disasmtool, so you can emulate raw binary files, and see their output. Note that this simple emulator supports basic x86/x64 instructions, and does not support emulating any kind of API call. In addition, the only supported memory accesses are inside the shellcode itself, and on the emulated stack.
|
||||||
emulate raw binary files, and see their output. Note that this simple emulator supports basic x86/x64 instructions, and does not support emulating any kind of API call. In addition, the only supported memory accesses are inside the shellcode itself, and on the emulated stack.
|
3. [isagenerator_x86](https://github.com/bitdefender/bddisasm/tree/master/isagenerator) - this project contains the instruction definitions and the scripts required to generate the disassembly tables. If you wish to add support for a new instruction, this is the place. This project will automatically generate several header files (instructions.h, mnemonics.h, constants.h, table_\*.h), so please make sure you don't manually edit any of these files. You will need Python 3 to run the generation scripts.
|
||||||
3. [isagenerator](https://github.com/bitdefender/bddisasm/tree/master/isagenerator) - this project contains the instruction definitions and the scripts required to generate the disassembly tables. If you wish to add support for a new instruction, this is the place. This project will automatically generate several header files (instructions.h, mnemonics.h, constants.h, table_\*.h), so please make sure you don't manually edit any of these files. You will need Python 3 to run the generation scripts.
|
|
||||||
4. [disasmtool](https://github.com/bitdefender/bddisasm/tree/master/disasmtool) - this project is a command line disassembler tool, used mainly as an example of how to integrate the bddisasm and bdshemu libraries.
|
4. [disasmtool](https://github.com/bitdefender/bddisasm/tree/master/disasmtool) - this project is a command line disassembler tool, used mainly as an example of how to integrate the bddisasm and bdshemu libraries.
|
||||||
5. [disasmtool_lix](https://github.com/bitdefender/bddisasm/tree/master/disasmtool_lix) - like disasmtool, but for Linux.
|
5. [bindings](https://github.com/bitdefender/bddisasm/tree/master/bindings) - bindings for [python](https://github.com/bitdefender/bddisasm/tree/master/bindings/pybddisasm), and [Rust](https://github.com/bitdefender/bddisasm/tree/master/bindings/rsbddisasm).
|
||||||
6. [bindings](https://github.com/bitdefender/bddisasm/tree/master/bindings) - bindings for [python](https://github.com/bitdefender/bddisasm/tree/master/bindings/pybddisasm), and [Rust](https://github.com/bitdefender/bddisasm/tree/master/bindings/rsbddisasm).
|
|
||||||
|
|
||||||
## Objectives
|
## Objectives
|
||||||
|
|
||||||
@ -161,7 +159,7 @@ The results will be in the bin directory in the root of the repository.
|
|||||||
|
|
||||||
[nd_vsnprintf_s and nd_memset](#nd_vsnprintf_s-and-nd_memset) will not be defined by `bddisasm`, integrators must provide these functions.
|
[nd_vsnprintf_s and nd_memset](#nd_vsnprintf_s-and-nd_memset) will not be defined by `bddisasm`, integrators must provide these functions.
|
||||||
|
|
||||||
## Decoding instructions
|
## Decoding x86 instructions
|
||||||
|
|
||||||
### Decoding API
|
### Decoding API
|
||||||
|
|
||||||
|
12
bddisasm.sln
12
bddisasm.sln
@ -15,7 +15,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bdshemu", "bdshemu\bdshemu.
|
|||||||
{3653AA19-048B-410E-B5C4-FF78E1D84C12} = {3653AA19-048B-410E-B5C4-FF78E1D84C12}
|
{3653AA19-048B-410E-B5C4-FF78E1D84C12} = {3653AA19-048B-410E-B5C4-FF78E1D84C12}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "isagenerator", "isagenerator\isagenerator.vcxproj", "{0E9D2957-34FA-40EE-B4B2-0D008D2FE317}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "isagenerator_x86", "isagenerator\isagenerator.vcxproj", "{0E9D2957-34FA-40EE-B4B2-0D008D2FE317}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{3114F0D4-BEBA-4574-A349-D03477C64C60}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{1F8BBB39-7787-4A50-8170-27EB5FA104D0}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -85,6 +89,12 @@ Global
|
|||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{94F1B65D-3305-4CCB-9DF1-50B56900D867} = {1F8BBB39-7787-4A50-8170-27EB5FA104D0}
|
||||||
|
{3653AA19-048B-410E-B5C4-FF78E1D84C12} = {3114F0D4-BEBA-4574-A349-D03477C64C60}
|
||||||
|
{3C9B2CA7-CF4F-471B-BB72-6490C476CDCA} = {3114F0D4-BEBA-4574-A349-D03477C64C60}
|
||||||
|
{0E9D2957-34FA-40EE-B4B2-0D008D2FE317} = {3114F0D4-BEBA-4574-A349-D03477C64C60}
|
||||||
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {E950FA16-07C1-4613-8328-906BC10C7C02}
|
SolutionGuid = {E950FA16-07C1-4613-8328-906BC10C7C02}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
SRC_FILES := crt.c bddisasm.c bdformat.c bdhelpers.c
|
SRC_FILES := bddisasm_crt.c bdx86_decoder.c bdx86_formatter.c bdx86_helpers.c
|
||||||
|
|
||||||
OBJECTS := $(SRC_FILES:.c=.o)
|
OBJECTS := $(SRC_FILES:.c=.o)
|
||||||
|
|
||||||
|
@ -115,7 +115,8 @@
|
|||||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<TargetVersion></TargetVersion>
|
<TargetVersion>
|
||||||
|
</TargetVersion>
|
||||||
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
|
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
|
||||||
<SupportsPackaging>false</SupportsPackaging>
|
<SupportsPackaging>false</SupportsPackaging>
|
||||||
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
||||||
@ -143,7 +144,8 @@
|
|||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<TargetVersion></TargetVersion>
|
<TargetVersion>
|
||||||
|
</TargetVersion>
|
||||||
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
|
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
|
||||||
<SupportsPackaging>false</SupportsPackaging>
|
<SupportsPackaging>false</SupportsPackaging>
|
||||||
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
||||||
@ -643,10 +645,10 @@
|
|||||||
</Lib>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="bdformat.c" />
|
<ClCompile Include="bdx86_formatter.c" />
|
||||||
<ClCompile Include="bdhelpers.c" />
|
<ClCompile Include="bdx86_helpers.c" />
|
||||||
<ClCompile Include="crt.c" />
|
<ClCompile Include="bddisasm_crt.c" />
|
||||||
<ClCompile Include="bddisasm.c">
|
<ClCompile Include="bdx86_decoder.c">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseKernel|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseKernel|Win32'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseKernel|x64'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseKernel|x64'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseKernel|ARM64'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseKernel|ARM64'">NotUsing</PrecompiledHeader>
|
||||||
@ -665,22 +667,23 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\inc\constants.h" />
|
<ClInclude Include="..\inc\bdx86_core.h" />
|
||||||
<ClInclude Include="..\inc\cpuidflags.h" />
|
<ClInclude Include="..\inc\bdx86_constants.h" />
|
||||||
|
<ClInclude Include="..\inc\bdx86_cpuidflags.h" />
|
||||||
<ClInclude Include="..\inc\bddisasm.h" />
|
<ClInclude Include="..\inc\bddisasm.h" />
|
||||||
<ClInclude Include="..\inc\disasmstatus.h" />
|
<ClInclude Include="..\inc\bddisasm_status.h" />
|
||||||
<ClInclude Include="..\inc\disasmtypes.h" />
|
<ClInclude Include="..\inc\bddisasm_types.h" />
|
||||||
<ClInclude Include="..\inc\registers.h" />
|
<ClInclude Include="..\inc\bdx86_registers.h" />
|
||||||
<ClInclude Include="..\inc\version.h" />
|
<ClInclude Include="..\inc\bddisasm_version.h" />
|
||||||
<ClInclude Include="include\instructions.h" />
|
<ClInclude Include="include\bdx86_instructions.h" />
|
||||||
<ClInclude Include="include\mnemonics.h" />
|
<ClInclude Include="include\bdx86_mnemonics.h" />
|
||||||
<ClInclude Include="include\nd_crt.h" />
|
<ClInclude Include="include\bddisasm_crt.h" />
|
||||||
<ClInclude Include="include\prefixes.h" />
|
<ClInclude Include="include\bdx86_prefixes.h" />
|
||||||
<ClInclude Include="include\tabledefs.h" />
|
<ClInclude Include="include\bdx86_tabledefs.h" />
|
||||||
<ClInclude Include="include\table_evex.h" />
|
<ClInclude Include="include\bdx86_table_evex.h" />
|
||||||
<ClInclude Include="include\table_root.h" />
|
<ClInclude Include="include\bdx86_table_root.h" />
|
||||||
<ClInclude Include="include\table_vex.h" />
|
<ClInclude Include="include\bdx86_table_vex.h" />
|
||||||
<ClInclude Include="include\table_xop.h" />
|
<ClInclude Include="include\bdx86_table_xop.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -19,69 +19,87 @@
|
|||||||
<Filter Include="Other">
|
<Filter Include="Other">
|
||||||
<UniqueIdentifier>{5e26c505-e8f5-4e6c-9d54-f20e36b637b8}</UniqueIdentifier>
|
<UniqueIdentifier>{5e26c505-e8f5-4e6c-9d54-f20e36b637b8}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Source Files\x86">
|
||||||
|
<UniqueIdentifier>{39065bbd-3fd0-42b0-ba8e-d7395674b7ce}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\public\x86">
|
||||||
|
<UniqueIdentifier>{032f0e51-6265-4031-b702-5eb620d95964}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\private">
|
||||||
|
<UniqueIdentifier>{5eb8f135-5960-4e0e-a5a8-5214a7a9edcb}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\private\x86">
|
||||||
|
<UniqueIdentifier>{db15a655-cc99-4e12-a8c3-55a485ee713c}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\private\x86\tables">
|
||||||
|
<UniqueIdentifier>{b9961460-d06f-4288-9708-44ca965c4a0d}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="crt.c">
|
<ClCompile Include="bddisasm_crt.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="bddisasm.c">
|
<ClCompile Include="bdx86_decoder.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files\x86</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="bdformat.c">
|
<ClCompile Include="bdx86_formatter.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files\x86</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="bdhelpers.c">
|
<ClCompile Include="bdx86_helpers.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files\x86</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\instructions.h">
|
<ClInclude Include="..\inc\bddisasm_version.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files\public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\mnemonics.h">
|
<ClInclude Include="..\inc\bdx86_constants.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files\public\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\prefixes.h">
|
<ClInclude Include="..\inc\bdx86_cpuidflags.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files\public\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\table_evex.h">
|
<ClInclude Include="..\inc\bddisasm_types.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files\public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\table_root.h">
|
<ClInclude Include="..\inc\bdx86_registers.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files\public\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\table_vex.h">
|
<ClInclude Include="..\inc\bddisasm_status.h">
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\table_xop.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\tabledefs.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\inc\constants.h">
|
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\bddisasm.h">
|
<ClInclude Include="..\inc\bddisasm.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\disasmstatus.h">
|
<ClInclude Include="..\inc\bdx86_core.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\public\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\disasmtypes.h">
|
<ClInclude Include="include\bdx86_instructions.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\private\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\registers.h">
|
<ClInclude Include="include\bdx86_mnemonics.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\private\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\version.h">
|
<ClInclude Include="include\bdx86_prefixes.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\private\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\cpuidflags.h">
|
<ClInclude Include="include\bdx86_tabledefs.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\private\x86</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\nd_crt.h">
|
<ClInclude Include="include\bddisasm_crt.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files\private</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\bdx86_table_evex.h">
|
||||||
|
<Filter>Header Files\private\x86\tables</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\bdx86_table_root.h">
|
||||||
|
<Filter>Header Files\private\x86\tables</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\bdx86_table_vex.h">
|
||||||
|
<Filter>Header Files\private\x86\tables</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\bdx86_table_xop.h">
|
||||||
|
<Filter>Header Files\private\x86\tables</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "include/nd_crt.h"
|
#include "include/bddisasm_crt.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// nd_strcat_s
|
// nd_strcat_s
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "include/nd_crt.h"
|
#include "include/bddisasm_crt.h"
|
||||||
#include "../inc/bddisasm.h"
|
#include "../inc/bddisasm.h"
|
||||||
|
|
||||||
|
|
||||||
@ -18,24 +18,32 @@ static const char *gReg8Bit64[] =
|
|||||||
{
|
{
|
||||||
"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
|
"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
|
||||||
"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b",
|
"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b",
|
||||||
|
"r16b", "r17b", "r18b", "r19b", "r20b", "r21b", "r22b", "r23b",
|
||||||
|
"r24b", "r25b", "r26b", "r27b", "r28b", "r29b", "r30b", "r31b",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gReg16Bit[] =
|
static const char *gReg16Bit[] =
|
||||||
{
|
{
|
||||||
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
|
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
|
||||||
"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",
|
"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",
|
||||||
|
"r16w", "r17w", "r18w", "r19w", "r20w", "r21w", "r22w", "r23w",
|
||||||
|
"r24w", "r25w", "r26w", "r27w", "r28w", "r29w", "r30w", "r31w",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gReg32Bit[] =
|
static const char *gReg32Bit[] =
|
||||||
{
|
{
|
||||||
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
|
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
|
||||||
"r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
|
"r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
|
||||||
|
"r16d", "r17d", "r18d", "r19d", "r20d", "r21d", "r22d", "r23d",
|
||||||
|
"r24d", "r25d", "r26d", "r27d", "r28d", "r29d", "r30d", "r31d",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gReg64Bit[] =
|
static const char *gReg64Bit[] =
|
||||||
{
|
{
|
||||||
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
|
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
|
||||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||||
|
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||||
|
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gRegFpu[] =
|
static const char *gRegFpu[] =
|
||||||
@ -52,12 +60,16 @@ static const char *gRegControl[] =
|
|||||||
{
|
{
|
||||||
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
|
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
|
||||||
"cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
|
"cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
|
||||||
|
"cr16", "cr17", "cr18", "cr19", "cr20", "cr21", "cr22", "cr23",
|
||||||
|
"cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gRegDebug[] =
|
static const char *gRegDebug[] =
|
||||||
{
|
{
|
||||||
"dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
|
"dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
|
||||||
"dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15",
|
"dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15",
|
||||||
|
"dr16", "dr17", "dr18", "dr19", "dr20", "dr21", "dr22", "dr23",
|
||||||
|
"dr24", "dr25", "dr26", "dr27", "dr28", "dr29", "dr30", "dr31",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gRegTest[] =
|
static const char *gRegTest[] =
|
||||||
@ -110,21 +122,12 @@ static const char *gRegTile[] =
|
|||||||
"tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7",
|
"tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gConditionCodes[] =
|
|
||||||
{
|
|
||||||
"EQ", "LT", "LE", "UNORD", "NEQ", "NLT", "NLE", "ORD",
|
|
||||||
"EQ_UQ", "NGE", "NGT", "ND_FALSE", "NEQ_OQ", "GE", "GT", "TRUE",
|
|
||||||
"EQ_OS", "LT_OQ", "LE_OQ", "UNORD_S", "NEQ_US", "NLT_UQ", "NLE_UQ", "ORD_S",
|
|
||||||
"EQ_US", "NGE_UQ", "NGT_UQ", "FALSE_OS", "NEQ_OS", "GE_OQ", "GT_OQ", "TRUE_US",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *gEmbeddedRounding[] =
|
static const char *gEmbeddedRounding[] =
|
||||||
{
|
{
|
||||||
"rn", "rd", "ru", "rz",
|
"rn", "rd", "ru", "rz",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// NdSprintf
|
// NdSprintf
|
||||||
//
|
//
|
||||||
@ -217,10 +220,9 @@ NdToText(
|
|||||||
nd_memzero(temp, sizeof(temp));
|
nd_memzero(temp, sizeof(temp));
|
||||||
|
|
||||||
// First, store the prefixes.
|
// First, store the prefixes.
|
||||||
if (Instrux->Rep != 0)
|
|
||||||
{
|
|
||||||
// Check for REPZ/REPNZ support, and store prefixes.
|
// Check for REPZ/REPNZ support, and store prefixes.
|
||||||
if (ND_REPC_SUPPORT(Instrux))
|
if (Instrux->IsRepcEnabled)
|
||||||
{
|
{
|
||||||
if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ)
|
if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ)
|
||||||
{
|
{
|
||||||
@ -235,7 +237,7 @@ NdToText(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for REP support and store prefixes.
|
// Check for REP support and store prefixes.
|
||||||
if (ND_REP_SUPPORT(Instrux))
|
if (Instrux->IsRepEnabled)
|
||||||
{
|
{
|
||||||
if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ)
|
if (Instrux->Rep == ND_PREFIX_G1_REPE_REPZ)
|
||||||
{
|
{
|
||||||
@ -259,27 +261,20 @@ NdToText(
|
|||||||
res = nd_strcat_s(Buffer, BufferSize, "XACQUIRE ");
|
res = nd_strcat_s(Buffer, BufferSize, "XACQUIRE ");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Instrux->HasLock)
|
if (Instrux->IsLockEnabled)
|
||||||
{
|
|
||||||
if (ND_LOCK_SUPPORT(Instrux))
|
|
||||||
{
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, "LOCK ");
|
res = nd_strcat_s(Buffer, BufferSize, "LOCK ");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Instrux->Rep == ND_PREFIX_G1_BND)
|
if (Instrux->IsBndEnabled)
|
||||||
{
|
|
||||||
if (ND_BND_SUPPORT(Instrux))
|
|
||||||
{
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, "BND ");
|
res = nd_strcat_s(Buffer, BufferSize, "BND ");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Instrux->HasSeg && ND_BHINT_SUPPORT(Instrux))
|
if (Instrux->IsBhintEnabled)
|
||||||
{
|
{
|
||||||
switch (Instrux->Seg)
|
switch (Instrux->Seg)
|
||||||
{
|
{
|
||||||
@ -303,23 +298,27 @@ NdToText(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Instrux->HasSeg && ND_DNT_SUPPORT(Instrux))
|
if (Instrux->IsDntEnabled)
|
||||||
{
|
|
||||||
if (!Instrux->IsCetTracked)
|
|
||||||
{
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, "DNT ");
|
res = nd_strcat_s(Buffer, BufferSize, "DNT ");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Store the mnemonic.
|
// Store the mnemonic.
|
||||||
res = nd_strcat_s(Buffer, BufferSize, Instrux->Mnemonic);
|
res = nd_strcat_s(Buffer, BufferSize, Instrux->Mnemonic);
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
// Store condition code, if any.
|
// Store NF specifier, if NoFlags presetn.
|
||||||
if (ND_HAS_SSE_CONDITION(Instrux))
|
if (Instrux->HasNf)
|
||||||
{
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gConditionCodes[Instrux->SseCondition]);
|
res = nd_strcat_s(Buffer, BufferSize, "{NF}");
|
||||||
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store ZU specifier, if ZeroUpper present.
|
||||||
|
if (Instrux->HasZu)
|
||||||
|
{
|
||||||
|
res = nd_strcat_s(Buffer, BufferSize, "{ZU}");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +405,7 @@ NdToText(
|
|||||||
{
|
{
|
||||||
case ND_SIZE_8BIT:
|
case ND_SIZE_8BIT:
|
||||||
// 8 bit register.
|
// 8 bit register.
|
||||||
if ((Instrux->EncMode != ND_ENCM_LEGACY) || Instrux->HasRex)
|
if ((Instrux->EncMode != ND_ENCM_LEGACY) || Instrux->HasRex || Instrux->HasRex2)
|
||||||
{
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit64[pOp->Info.Register.Reg]);
|
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit64[pOp->Info.Register.Reg]);
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
@ -444,11 +443,6 @@ NdToText(
|
|||||||
|
|
||||||
case ND_REG_SEG:
|
case ND_REG_SEG:
|
||||||
{
|
{
|
||||||
if (pOp->Info.Register.Reg >= ND_MAX_SEG_REGS)
|
|
||||||
{
|
|
||||||
return ND_STATUS_INVALID_INSTRUX;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gRegSeg[pOp->Info.Register.Reg]);
|
res = nd_strcat_s(Buffer, BufferSize, gRegSeg[pOp->Info.Register.Reg]);
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
@ -671,7 +665,7 @@ NdToText(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ND_OP_ADDR:
|
case ND_OP_ADDR_FAR:
|
||||||
{
|
{
|
||||||
switch (Instrux->AddrLength)
|
switch (Instrux->AddrLength)
|
||||||
{
|
{
|
||||||
@ -701,6 +695,36 @@ NdToText(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ND_OP_ADDR_NEAR:
|
||||||
|
{
|
||||||
|
status = NdSprintf(temp, sizeof(temp), "0x%016llx", pOp->Info.AddressNear.Target);
|
||||||
|
if (!ND_SUCCESS(status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = nd_strcat_s(Buffer, BufferSize, temp);
|
||||||
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_OP_DFV:
|
||||||
|
{
|
||||||
|
status = NdSprintf(temp, sizeof(temp), "%c%c%c%c",
|
||||||
|
pOp->Info.DefaultFlags.OF ? '1' : '0',
|
||||||
|
pOp->Info.DefaultFlags.SF ? '1' : '0',
|
||||||
|
pOp->Info.DefaultFlags.ZF ? '1' : '0',
|
||||||
|
pOp->Info.DefaultFlags.CF ? '1' : '0');
|
||||||
|
if (!ND_SUCCESS(status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = nd_strcat_s(Buffer, BufferSize, temp);
|
||||||
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ND_OP_MEM:
|
case ND_OP_MEM:
|
||||||
{
|
{
|
||||||
// Prepend the size. For VSIB addressing, store the VSIB element size, not the total accessed size.
|
// Prepend the size. For VSIB addressing, store the VSIB element size, not the total accessed size.
|
||||||
@ -755,11 +779,6 @@ NdToText(
|
|||||||
// Perpend the segment, only if it is overridden via a prefix.
|
// Perpend the segment, only if it is overridden via a prefix.
|
||||||
if (pOp->Info.Memory.HasSeg && Instrux->HasSeg)
|
if (pOp->Info.Memory.HasSeg && Instrux->HasSeg)
|
||||||
{
|
{
|
||||||
if (pOp->Info.Memory.Seg >= ND_MAX_SEG_REGS)
|
|
||||||
{
|
|
||||||
return ND_STATUS_INVALID_INSTRUX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ND_CODE_64 != Instrux->DefCode) || (NDR_FS == pOp->Info.Memory.Seg) ||
|
if ((ND_CODE_64 != Instrux->DefCode) || (NDR_FS == pOp->Info.Memory.Seg) ||
|
||||||
(NDR_GS == pOp->Info.Memory.Seg))
|
(NDR_GS == pOp->Info.Memory.Seg))
|
||||||
{
|
{
|
||||||
@ -778,16 +797,20 @@ NdToText(
|
|||||||
// Base, if any.
|
// Base, if any.
|
||||||
if (pOp->Info.Memory.HasBase)
|
if (pOp->Info.Memory.HasBase)
|
||||||
{
|
{
|
||||||
if (pOp->Info.Memory.Base >= ND_MAX_GPR_REGS)
|
|
||||||
{
|
|
||||||
return ND_STATUS_INVALID_INSTRUX;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pOp->Info.Memory.BaseSize)
|
switch (pOp->Info.Memory.BaseSize)
|
||||||
{
|
{
|
||||||
case ND_SIZE_8BIT:
|
case ND_SIZE_8BIT:
|
||||||
|
if ((Instrux->EncMode != ND_ENCM_LEGACY) || Instrux->HasRex || Instrux->HasRex2)
|
||||||
|
{
|
||||||
|
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit64[pOp->Info.Memory.Base]);
|
||||||
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Base]);
|
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Base]);
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ND_SIZE_16BIT:
|
case ND_SIZE_16BIT:
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Base]);
|
res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Base]);
|
||||||
@ -823,8 +846,16 @@ NdToText(
|
|||||||
switch (pOp->Info.Memory.IndexSize)
|
switch (pOp->Info.Memory.IndexSize)
|
||||||
{
|
{
|
||||||
case ND_SIZE_8BIT:
|
case ND_SIZE_8BIT:
|
||||||
|
if ((Instrux->EncMode != ND_ENCM_LEGACY) || Instrux->HasRex || Instrux->HasRex2)
|
||||||
|
{
|
||||||
|
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit64[pOp->Info.Memory.Index]);
|
||||||
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Index]);
|
res = nd_strcat_s(Buffer, BufferSize, gReg8Bit[pOp->Info.Memory.Index]);
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ND_SIZE_16BIT:
|
case ND_SIZE_16BIT:
|
||||||
res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Index]);
|
res = nd_strcat_s(Buffer, BufferSize, gReg16Bit[pOp->Info.Memory.Index]);
|
||||||
@ -913,7 +944,18 @@ NdToText(
|
|||||||
// Now displacement.
|
// Now displacement.
|
||||||
if (pOp->Info.Memory.HasBase || pOp->Info.Memory.HasIndex)
|
if (pOp->Info.Memory.HasBase || pOp->Info.Memory.HasIndex)
|
||||||
{
|
{
|
||||||
res = nd_strcat_s(Buffer, BufferSize, Instrux->SignDisp ? "-" : "+");
|
ND_BOOL sign;
|
||||||
|
|
||||||
|
if (ND_GET_SIGN(8, pOp->Info.Memory.Disp))
|
||||||
|
{
|
||||||
|
sign = ND_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sign = ND_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = nd_strcat_s(Buffer, BufferSize, sign ? "-" : "+");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,17 +993,11 @@ NdToText(
|
|||||||
// And the ending "]"
|
// And the ending "]"
|
||||||
res = nd_strcat_s(Buffer, BufferSize, "]");
|
res = nd_strcat_s(Buffer, BufferSize, "]");
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return ND_STATUS_INVALID_INSTRUX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle memory broadcast.
|
// Handle memory broadcast.
|
||||||
if (pOp->Decorator.HasBroadcast)
|
if (pOp->Info.Memory.HasBroadcast)
|
||||||
{
|
{
|
||||||
status = NdSprintf(temp, sizeof(temp), "{1to%d}", pOp->Decorator.Broadcast.Count);
|
status = NdSprintf(temp, sizeof(temp), "{1to%d}", pOp->Info.Memory.Broadcast.Count);
|
||||||
if (!ND_SUCCESS(status))
|
if (!ND_SUCCESS(status))
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
@ -970,16 +1006,17 @@ NdToText(
|
|||||||
res = nd_strcat_s(Buffer, BufferSize, temp);
|
res = nd_strcat_s(Buffer, BufferSize, temp);
|
||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ND_STATUS_INVALID_INSTRUX;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle masking.
|
// Handle masking.
|
||||||
if (pOp->Decorator.HasMask)
|
if (pOp->Decorator.HasMask)
|
||||||
{
|
{
|
||||||
if (pOp->Decorator.Mask.Msk >= ND_MAX_MSK_REGS)
|
status = NdSprintf(temp, sizeof(temp), "{%s}", gRegMask[pOp->Decorator.Msk]);
|
||||||
{
|
|
||||||
return ND_STATUS_INVALID_INSTRUX;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = NdSprintf(temp, sizeof(temp), "{%s}", gRegMask[pOp->Decorator.Mask.Msk]);
|
|
||||||
if (!ND_SUCCESS(status))
|
if (!ND_SUCCESS(status))
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
@ -996,8 +1033,12 @@ NdToText(
|
|||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is the last reg/mem operand, display {sae} and {er} decorators.
|
||||||
|
if ((pOp->Type == ND_OP_MEM || pOp->Type == ND_OP_REG) &&
|
||||||
|
(opIndex + 1 >= Instrux->ExpOperandsCount || Instrux->Operands[opIndex + 1].Type == ND_OP_IMM))
|
||||||
|
{
|
||||||
// Append Suppress All Exceptions decorator.
|
// Append Suppress All Exceptions decorator.
|
||||||
if (pOp->Decorator.HasSae && !pOp->Decorator.HasEr)
|
if (Instrux->HasSae && !Instrux->HasEr)
|
||||||
{
|
{
|
||||||
// ER implies SAE, so if we have ER, we will list that.
|
// ER implies SAE, so if we have ER, we will list that.
|
||||||
res = nd_strcat_s(Buffer, BufferSize, ", {sae}");
|
res = nd_strcat_s(Buffer, BufferSize, ", {sae}");
|
||||||
@ -1005,13 +1046,8 @@ NdToText(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append Embedded Rounding decorator.
|
// Append Embedded Rounding decorator.
|
||||||
if (pOp->Decorator.HasEr)
|
if (Instrux->HasEr)
|
||||||
{
|
{
|
||||||
if (Instrux->RoundingMode >= 4)
|
|
||||||
{
|
|
||||||
return ND_STATUS_INVALID_INSTRUX;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = NdSprintf(temp, sizeof(temp), ", {%s-sae}", gEmbeddedRounding[Instrux->RoundingMode]);
|
status = NdSprintf(temp, sizeof(temp), ", {%s-sae}", gEmbeddedRounding[Instrux->RoundingMode]);
|
||||||
if (!ND_SUCCESS(status))
|
if (!ND_SUCCESS(status))
|
||||||
{
|
{
|
||||||
@ -1022,6 +1058,7 @@ NdToText(
|
|||||||
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
RET_EQ(res, ND_NULL, ND_STATUS_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ND_STATUS_SUCCESS;
|
return ND_STATUS_SUCCESS;
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "include/nd_crt.h"
|
#include "include/bddisasm_crt.h"
|
||||||
#include "../inc/bddisasm.h"
|
#include "../inc/bddisasm.h"
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
#ifndef ND_CRT_H
|
#ifndef ND_CRT_H
|
||||||
#define ND_CRT_H
|
#define ND_CRT_H
|
||||||
|
|
||||||
#include "../../inc/disasmtypes.h"
|
#include "../../inc/bddisasm_types.h"
|
||||||
|
|
||||||
#ifndef UNREFERENCED_PARAMETER
|
#ifndef UNREFERENCED_PARAMETER
|
||||||
#define UNREFERENCED_PARAMETER(P) ((void)(P))
|
#define UNREFERENCED_PARAMETER(P) ((void)(P))
|
114205
bddisasm/include/bdx86_instructions.h
Normal file
114205
bddisasm/include/bdx86_instructions.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2024 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -7,39 +7,46 @@
|
|||||||
// This file was auto-generated by generate_tables.py. DO NOT MODIFY!
|
// This file was auto-generated by generate_tables.py. DO NOT MODIFY!
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef MNEMONICS_H
|
#ifndef BDX86_MNEMONICS_H
|
||||||
#define MNEMONICS_H
|
#define BDX86_MNEMONICS_H
|
||||||
|
|
||||||
const char *gMnemonics[1751] =
|
const char *gMnemonics[1786] =
|
||||||
{
|
{
|
||||||
"AAA", "AAD", "AADD", "AAM", "AAND", "AAS", "ADC", "ADCX", "ADD",
|
"AAA", "AAD", "AADD", "AAM", "AAND", "AAS", "ADC", "ADCX", "ADD",
|
||||||
"ADDPD", "ADDPS", "ADDSD", "ADDSS", "ADDSUBPD", "ADDSUBPS", "ADOX",
|
"ADDPD", "ADDPS", "ADDSD", "ADDSS", "ADDSUBPD", "ADDSUBPS", "ADOX",
|
||||||
"AESDEC", "AESDEC128KL", "AESDEC256KL", "AESDECLAST", "AESDECWIDE128KL",
|
"AESDEC", "AESDEC128KL", "AESDEC256KL", "AESDECLAST", "AESDECWIDE128KL",
|
||||||
"AESDECWIDE256KL", "AESENC", "AESENC128KL", "AESENC256KL", "AESENCLAST",
|
"AESDECWIDE256KL", "AESENC", "AESENC128KL", "AESENC256KL", "AESENCLAST",
|
||||||
"AESENCWIDE128KL", "AESENCWIDE256KL", "AESIMC", "AESKEYGENASSIST",
|
"AESENCWIDE128KL", "AESENCWIDE256KL", "AESIMC", "AESKEYGENASSIST",
|
||||||
"ALTINST", "AND", "ANDN", "ANDNPD", "ANDNPS", "ANDPD", "ANDPS",
|
"AND", "ANDN", "ANDNPD", "ANDNPS", "ANDPD", "ANDPS", "AOR", "ARPL",
|
||||||
"AOR", "ARPL", "AXOR", "BEXTR", "BLCFILL", "BLCI", "BLCIC", "BLCMSK",
|
"AXOR", "BEXTR", "BLCFILL", "BLCI", "BLCIC", "BLCMSK", "BLCS",
|
||||||
"BLCS", "BLENDPD", "BLENDPS", "BLENDVPD", "BLENDVPS", "BLSFILL",
|
"BLENDPD", "BLENDPS", "BLENDVPD", "BLENDVPS", "BLSFILL", "BLSI",
|
||||||
"BLSI", "BLSIC", "BLSMSK", "BLSR", "BNDCL", "BNDCN", "BNDCU",
|
"BLSIC", "BLSMSK", "BLSR", "BNDCL", "BNDCN", "BNDCU", "BNDLDX",
|
||||||
"BNDLDX", "BNDMK", "BNDMOV", "BNDSTX", "BOUND", "BSF", "BSR",
|
"BNDMK", "BNDMOV", "BNDSTX", "BOUND", "BSF", "BSR", "BSWAP",
|
||||||
"BSWAP", "BT", "BTC", "BTR", "BTS", "BZHI", "CALL", "CALLF",
|
"BT", "BTC", "BTR", "BTS", "BZHI", "CALL", "CALLF", "CBW", "CCMPBE",
|
||||||
"CBW", "CDQ", "CDQE", "CLAC", "CLC", "CLD", "CLDEMOTE", "CLEVICT0",
|
"CCMPC", "CCMPF", "CCMPL", "CCMPLE", "CCMPNBE", "CCMPNC", "CCMPNL",
|
||||||
"CLEVICT1", "CLFLUSH", "CLFLUSHOPT", "CLGI", "CLI", "CLRSSBSY",
|
"CCMPNLE", "CCMPNO", "CCMPNS", "CCMPNZ", "CCMPO", "CCMPS", "CCMPT",
|
||||||
"CLTS", "CLUI", "CLWB", "CLZERO", "CMC", "CMOVBE", "CMOVC", "CMOVL",
|
"CCMPZ", "CDQ", "CDQE", "CFCMOVBE", "CFCMOVC", "CFCMOVL", "CFCMOVLE",
|
||||||
"CMOVLE", "CMOVNBE", "CMOVNC", "CMOVNL", "CMOVNLE", "CMOVNO",
|
"CFCMOVNBE", "CFCMOVNC", "CFCMOVNL", "CFCMOVNLE", "CFCMOVNO",
|
||||||
"CMOVNP", "CMOVNS", "CMOVNZ", "CMOVO", "CMOVP", "CMOVS", "CMOVZ",
|
"CFCMOVNP", "CFCMOVNS", "CFCMOVNZ", "CFCMOVO", "CFCMOVP", "CFCMOVS",
|
||||||
"CMP", "CMPBEXADD", "CMPCXADD", "CMPLEXADD", "CMPLXADD", "CMPNBEXADD",
|
"CFCMOVZ", "CLAC", "CLC", "CLD", "CLDEMOTE", "CLEVICT0", "CLEVICT1",
|
||||||
|
"CLFLUSH", "CLFLUSHOPT", "CLGI", "CLI", "CLRSSBSY", "CLTS", "CLUI",
|
||||||
|
"CLWB", "CLZERO", "CMC", "CMOVBE", "CMOVC", "CMOVL", "CMOVLE",
|
||||||
|
"CMOVNBE", "CMOVNC", "CMOVNL", "CMOVNLE", "CMOVNO", "CMOVNP",
|
||||||
|
"CMOVNS", "CMOVNZ", "CMOVO", "CMOVP", "CMOVS", "CMOVZ", "CMP",
|
||||||
|
"CMPBEXADD", "CMPCXADD", "CMPLEXADD", "CMPLXADD", "CMPNBEXADD",
|
||||||
"CMPNCXADD", "CMPNLEXADD", "CMPNLXADD", "CMPNOXADD", "CMPNPXADD",
|
"CMPNCXADD", "CMPNLEXADD", "CMPNLXADD", "CMPNOXADD", "CMPNPXADD",
|
||||||
"CMPNSXADD", "CMPNZXADD", "CMPOXADD", "CMPPD", "CMPPS", "CMPPXADD",
|
"CMPNSXADD", "CMPNZXADD", "CMPOXADD", "CMPPD", "CMPPS", "CMPPXADD",
|
||||||
"CMPSB", "CMPSD", "CMPSQ", "CMPSS", "CMPSW", "CMPSXADD", "CMPXCHG",
|
"CMPSB", "CMPSD", "CMPSQ", "CMPSS", "CMPSW", "CMPSXADD", "CMPXCHG",
|
||||||
"CMPXCHG16B", "CMPXCHG8B", "CMPZXADD", "COMISD", "COMISS", "CPUID",
|
"CMPXCHG16B", "CMPXCHG8B", "CMPZXADD", "COMISD", "COMISS", "CPUID",
|
||||||
"CPU_READ", "CPU_WRITE", "CQO", "CRC32", "CVTDQ2PD", "CVTDQ2PS",
|
"CQO", "CRC32", "CTESTBE", "CTESTC", "CTESTF", "CTESTL", "CTESTLE",
|
||||||
"CVTPD2DQ", "CVTPD2PI", "CVTPD2PS", "CVTPI2PD", "CVTPI2PS", "CVTPS2DQ",
|
"CTESTNBE", "CTESTNC", "CTESTNL", "CTESTNLE", "CTESTNO", "CTESTNS",
|
||||||
"CVTPS2PD", "CVTPS2PI", "CVTSD2SI", "CVTSD2SS", "CVTSI2SD", "CVTSI2SS",
|
"CTESTNZ", "CTESTO", "CTESTS", "CTESTT", "CTESTZ", "CVTDQ2PD",
|
||||||
"CVTSS2SD", "CVTSS2SI", "CVTTPD2DQ", "CVTTPD2PI", "CVTTPS2DQ",
|
"CVTDQ2PS", "CVTPD2DQ", "CVTPD2PI", "CVTPD2PS", "CVTPI2PD", "CVTPI2PS",
|
||||||
"CVTTPS2PI", "CVTTSD2SI", "CVTTSS2SI", "CWD", "CWDE", "DAA",
|
"CVTPS2DQ", "CVTPS2PD", "CVTPS2PI", "CVTSD2SI", "CVTSD2SS", "CVTSI2SD",
|
||||||
"DAS", "DEC", "DELAY", "DIV", "DIVPD", "DIVPS", "DIVSD", "DIVSS",
|
"CVTSI2SS", "CVTSS2SD", "CVTSS2SI", "CVTTPD2DQ", "CVTTPD2PI",
|
||||||
"DMINT", "DPPD", "DPPS", "EMMS", "ENCLS", "ENCLU", "ENCLV", "ENCODEKEY128",
|
"CVTTPS2DQ", "CVTTPS2PI", "CVTTSD2SI", "CVTTSS2SI", "CWD", "CWDE",
|
||||||
|
"DAA", "DAS", "DEC", "DELAY", "DIV", "DIVPD", "DIVPS", "DIVSD",
|
||||||
|
"DIVSS", "DPPD", "DPPS", "EMMS", "ENCLS", "ENCLU", "ENCLV", "ENCODEKEY128",
|
||||||
"ENCODEKEY256", "ENDBR32", "ENDBR64", "ENQCMD", "ENQCMDS", "ENTER",
|
"ENCODEKEY256", "ENDBR32", "ENDBR64", "ENQCMD", "ENQCMDS", "ENTER",
|
||||||
"ERETS", "ERETU", "EXTRACTPS", "EXTRQ", "F2XM1", "FABS", "FADD",
|
"ERETS", "ERETU", "EXTRACTPS", "EXTRQ", "F2XM1", "FABS", "FADD",
|
||||||
"FADDP", "FBLD", "FBSTP", "FCHS", "FCMOVB", "FCMOVBE", "FCMOVE",
|
"FADDP", "FBLD", "FBSTP", "FCHS", "FCMOVB", "FCMOVBE", "FCMOVE",
|
||||||
@ -61,24 +68,24 @@ const char *gMnemonics[1751] =
|
|||||||
"INCSSPD", "INCSSPQ", "INSB", "INSD", "INSERTPS", "INSERTQ",
|
"INCSSPD", "INCSSPQ", "INSB", "INSD", "INSERTPS", "INSERTQ",
|
||||||
"INSW", "INT", "INT1", "INT3", "INTO", "INVD", "INVEPT", "INVLPG",
|
"INSW", "INT", "INT1", "INT3", "INTO", "INVD", "INVEPT", "INVLPG",
|
||||||
"INVLPGA", "INVLPGB", "INVPCID", "INVVPID", "IRETD", "IRETQ",
|
"INVLPGA", "INVLPGB", "INVPCID", "INVVPID", "IRETD", "IRETQ",
|
||||||
"IRETW", "JBE", "JC", "JCXZ", "JECXZ", "JL", "JLE", "JMP", "JMPE",
|
"IRETW", "JBE", "JC", "JCXZ", "JECXZ", "JL", "JLE", "JMP", "JMPABS",
|
||||||
"JMPF", "JNBE", "JNC", "JNL", "JNLE", "JNO", "JNP", "JNS", "JNZ",
|
"JMPE", "JMPF", "JNBE", "JNC", "JNL", "JNLE", "JNO", "JNP", "JNS",
|
||||||
"JO", "JP", "JRCXZ", "JS", "JZ", "KADDB", "KADDD", "KADDQ", "KADDW",
|
"JNZ", "JO", "JP", "JRCXZ", "JS", "JZ", "KADDB", "KADDD", "KADDQ",
|
||||||
"KANDB", "KANDD", "KANDNB", "KANDND", "KANDNQ", "KANDNW", "KANDQ",
|
"KADDW", "KANDB", "KANDD", "KANDNB", "KANDND", "KANDNQ", "KANDNW",
|
||||||
"KANDW", "KMERGE2L1H", "KMERGE2L1L", "KMOVB", "KMOVD", "KMOVQ",
|
"KANDQ", "KANDW", "KMERGE2L1H", "KMERGE2L1L", "KMOVB", "KMOVD",
|
||||||
"KMOVW", "KNOTB", "KNOTD", "KNOTQ", "KNOTW", "KORB", "KORD",
|
"KMOVQ", "KMOVW", "KNOTB", "KNOTD", "KNOTQ", "KNOTW", "KORB",
|
||||||
"KORQ", "KORTESTB", "KORTESTD", "KORTESTQ", "KORTESTW", "KORW",
|
"KORD", "KORQ", "KORTESTB", "KORTESTD", "KORTESTQ", "KORTESTW",
|
||||||
"KSHIFTLB", "KSHIFTLD", "KSHIFTLQ", "KSHIFTLW", "KSHIFTRB", "KSHIFTRD",
|
"KORW", "KSHIFTLB", "KSHIFTLD", "KSHIFTLQ", "KSHIFTLW", "KSHIFTRB",
|
||||||
"KSHIFTRQ", "KSHIFTRW", "KTESTB", "KTESTD", "KTESTQ", "KTESTW",
|
"KSHIFTRD", "KSHIFTRQ", "KSHIFTRW", "KTESTB", "KTESTD", "KTESTQ",
|
||||||
"KUNPCKBW", "KUNPCKDQ", "KUNPCKWD", "KXNORB", "KXNORD", "KXNORQ",
|
"KTESTW", "KUNPCKBW", "KUNPCKDQ", "KUNPCKWD", "KXNORB", "KXNORD",
|
||||||
"KXNORW", "KXORB", "KXORD", "KXORQ", "KXORW", "LAHF", "LAR",
|
"KXNORQ", "KXNORW", "KXORB", "KXORD", "KXORQ", "KXORW", "LAHF",
|
||||||
"LDDQU", "LDMXCSR", "LDS", "LDTILECFG", "LEA", "LEAVE", "LES",
|
"LAR", "LDDQU", "LDMXCSR", "LDS", "LDTILECFG", "LEA", "LEAVE",
|
||||||
"LFENCE", "LFS", "LGDT", "LGS", "LIDT", "LKGS", "LLDT", "LLWPCB",
|
"LES", "LFENCE", "LFS", "LGDT", "LGS", "LIDT", "LKGS", "LLDT",
|
||||||
"LMSW", "LOADIWKEY", "LODSB", "LODSD", "LODSQ", "LODSW", "LOOP",
|
"LLWPCB", "LMSW", "LOADIWKEY", "LODSB", "LODSD", "LODSQ", "LODSW",
|
||||||
"LOOPNZ", "LOOPZ", "LSL", "LSS", "LTR", "LWPINS", "LWPVAL", "LZCNT",
|
"LOOP", "LOOPNZ", "LOOPZ", "LSL", "LSS", "LTR", "LWPINS", "LWPVAL",
|
||||||
"MASKMOVDQU", "MASKMOVQ", "MAXPD", "MAXPS", "MAXSD", "MAXSS",
|
"LZCNT", "MASKMOVDQU", "MASKMOVQ", "MAXPD", "MAXPS", "MAXSD",
|
||||||
"MCOMMIT", "MFENCE", "MINPD", "MINPS", "MINSD", "MINSS", "MONITOR",
|
"MAXSS", "MCOMMIT", "MFENCE", "MINPD", "MINPS", "MINSD", "MINSS",
|
||||||
"MONITORX", "MONTMUL", "MOV", "MOVAPD", "MOVAPS", "MOVBE", "MOVD",
|
"MONITOR", "MONITORX", "MOV", "MOVAPD", "MOVAPS", "MOVBE", "MOVD",
|
||||||
"MOVDDUP", "MOVDIR64B", "MOVDIRI", "MOVDQ2Q", "MOVDQA", "MOVDQU",
|
"MOVDDUP", "MOVDIR64B", "MOVDIRI", "MOVDQ2Q", "MOVDQA", "MOVDQU",
|
||||||
"MOVHLPS", "MOVHPD", "MOVHPS", "MOVLHPS", "MOVLPD", "MOVLPS",
|
"MOVHLPS", "MOVHPD", "MOVHPS", "MOVLHPS", "MOVLPD", "MOVLPS",
|
||||||
"MOVMSKPD", "MOVMSKPS", "MOVNTDQ", "MOVNTDQA", "MOVNTI", "MOVNTPD",
|
"MOVMSKPD", "MOVMSKPS", "MOVNTDQ", "MOVNTDQA", "MOVNTI", "MOVNTPD",
|
||||||
@ -104,52 +111,52 @@ const char *gMnemonics[1751] =
|
|||||||
"PMINUD", "PMINUW", "PMOVMSKB", "PMOVSXBD", "PMOVSXBQ", "PMOVSXBW",
|
"PMINUD", "PMINUW", "PMOVMSKB", "PMOVSXBD", "PMOVSXBQ", "PMOVSXBW",
|
||||||
"PMOVSXDQ", "PMOVSXWD", "PMOVSXWQ", "PMOVZXBD", "PMOVZXBQ", "PMOVZXBW",
|
"PMOVSXDQ", "PMOVSXWD", "PMOVSXWQ", "PMOVZXBD", "PMOVZXBQ", "PMOVZXBW",
|
||||||
"PMOVZXDQ", "PMOVZXWD", "PMOVZXWQ", "PMULDQ", "PMULHRSW", "PMULHRW",
|
"PMOVZXDQ", "PMOVZXWD", "PMOVZXWQ", "PMULDQ", "PMULHRSW", "PMULHRW",
|
||||||
"PMULHUW", "PMULHW", "PMULLD", "PMULLW", "PMULUDQ", "POP", "POPA",
|
"PMULHUW", "PMULHW", "PMULLD", "PMULLW", "PMULUDQ", "POP", "POP2",
|
||||||
"POPAD", "POPCNT", "POPFD", "POPFQ", "POPFW", "POR", "PREFETCH",
|
"POP2P", "POPA", "POPAD", "POPCNT", "POPFD", "POPFQ", "POPFW",
|
||||||
"PREFETCHE", "PREFETCHIT0", "PREFETCHIT1", "PREFETCHM", "PREFETCHNTA",
|
"POPP", "POR", "PREFETCH", "PREFETCHE", "PREFETCHIT0", "PREFETCHIT1",
|
||||||
"PREFETCHT0", "PREFETCHT1", "PREFETCHT2", "PREFETCHW", "PREFETCHWT1",
|
"PREFETCHM", "PREFETCHNTA", "PREFETCHT0", "PREFETCHT1", "PREFETCHT2",
|
||||||
"PSADBW", "PSHUFB", "PSHUFD", "PSHUFHW", "PSHUFLW", "PSHUFW",
|
"PREFETCHW", "PREFETCHWT1", "PSADBW", "PSHUFB", "PSHUFD", "PSHUFHW",
|
||||||
"PSIGNB", "PSIGND", "PSIGNW", "PSLLD", "PSLLDQ", "PSLLQ", "PSLLW",
|
"PSHUFLW", "PSHUFW", "PSIGNB", "PSIGND", "PSIGNW", "PSLLD", "PSLLDQ",
|
||||||
"PSMASH", "PSRAD", "PSRAW", "PSRLD", "PSRLDQ", "PSRLQ", "PSRLW",
|
"PSLLQ", "PSLLW", "PSMASH", "PSRAD", "PSRAW", "PSRLD", "PSRLDQ",
|
||||||
"PSUBB", "PSUBD", "PSUBQ", "PSUBSB", "PSUBSW", "PSUBUSB", "PSUBUSW",
|
"PSRLQ", "PSRLW", "PSUBB", "PSUBD", "PSUBQ", "PSUBSB", "PSUBSW",
|
||||||
"PSUBW", "PSWAPD", "PTEST", "PTWRITE", "PUNPCKHBW", "PUNPCKHDQ",
|
"PSUBUSB", "PSUBUSW", "PSUBW", "PSWAPD", "PTEST", "PTWRITE",
|
||||||
"PUNPCKHQDQ", "PUNPCKHWD", "PUNPCKLBW", "PUNPCKLDQ", "PUNPCKLQDQ",
|
"PUNPCKHBW", "PUNPCKHDQ", "PUNPCKHQDQ", "PUNPCKHWD", "PUNPCKLBW",
|
||||||
"PUNPCKLWD", "PUSH", "PUSHA", "PUSHAD", "PUSHFD", "PUSHFQ", "PUSHFW",
|
"PUNPCKLDQ", "PUNPCKLQDQ", "PUNPCKLWD", "PUSH", "PUSH2", "PUSH2P",
|
||||||
"PVALIDATE", "PXOR", "RCL", "RCPPS", "RCPSS", "RCR", "RDFSBASE",
|
"PUSHA", "PUSHAD", "PUSHFD", "PUSHFQ", "PUSHFW", "PUSHP", "PVALIDATE",
|
||||||
"RDGSBASE", "RDMSR", "RDMSRLIST", "RDPID", "RDPKRU", "RDPMC",
|
"PXOR", "RCL", "RCPPS", "RCPSS", "RCR", "RDFSBASE", "RDGSBASE",
|
||||||
"RDPRU", "RDRAND", "RDSEED", "RDSHR", "RDSSPD", "RDSSPQ", "RDTSC",
|
"RDMSR", "RDMSRLIST", "RDPID", "RDPKRU", "RDPMC", "RDPRU", "RDRAND",
|
||||||
"RDTSCP", "RETF", "RETN", "RMPADJUST", "RMPQUERY", "RMPUPDATE",
|
"RDSEED", "RDSSPD", "RDSSPQ", "RDTSC", "RDTSCP", "RETF", "RETN",
|
||||||
"ROL", "ROR", "RORX", "ROUNDPD", "ROUNDPS", "ROUNDSD", "ROUNDSS",
|
"RMPADJUST", "RMPQUERY", "RMPUPDATE", "ROL", "ROR", "RORX", "ROUNDPD",
|
||||||
"RSDC", "RSLDT", "RSM", "RSQRTPS", "RSQRTSS", "RSTORSSP", "RSTS",
|
"ROUNDPS", "ROUNDSD", "ROUNDSS", "RSM", "RSQRTPS", "RSQRTSS",
|
||||||
"SAHF", "SAL", "SALC", "SAR", "SARX", "SAVEPREVSSP", "SBB", "SCASB",
|
"RSTORSSP", "SAHF", "SAL", "SALC", "SAR", "SARX", "SAVEPREVSSP",
|
||||||
"SCASD", "SCASQ", "SCASW", "SEAMCALL", "SEAMOPS", "SEAMRET",
|
"SBB", "SCASB", "SCASD", "SCASQ", "SCASW", "SEAMCALL", "SEAMOPS",
|
||||||
"SENDUIPI", "SERIALIZE", "SETBE", "SETC", "SETL", "SETLE", "SETNBE",
|
"SEAMRET", "SENDUIPI", "SERIALIZE", "SETBE", "SETC", "SETL",
|
||||||
"SETNC", "SETNL", "SETNLE", "SETNO", "SETNP", "SETNS", "SETNZ",
|
"SETLE", "SETNBE", "SETNC", "SETNL", "SETNLE", "SETNO", "SETNP",
|
||||||
"SETO", "SETP", "SETS", "SETSSBSY", "SETZ", "SFENCE", "SGDT",
|
"SETNS", "SETNZ", "SETO", "SETP", "SETS", "SETSSBSY", "SETZ",
|
||||||
"SHA1MSG1", "SHA1MSG2", "SHA1NEXTE", "SHA1RNDS4", "SHA256MSG1",
|
"SFENCE", "SGDT", "SHA1MSG1", "SHA1MSG2", "SHA1NEXTE", "SHA1RNDS4",
|
||||||
"SHA256MSG2", "SHA256RNDS2", "SHL", "SHLD", "SHLX", "SHR", "SHRD",
|
"SHA256MSG1", "SHA256MSG2", "SHA256RNDS2", "SHL", "SHLD", "SHLX",
|
||||||
"SHRX", "SHUFPD", "SHUFPS", "SIDT", "SKINIT", "SLDT", "SLWPCB",
|
"SHR", "SHRD", "SHRX", "SHUFPD", "SHUFPS", "SIDT", "SKINIT",
|
||||||
"SMINT", "SMSW", "SPFLT", "SQRTPD", "SQRTPS", "SQRTSD", "SQRTSS",
|
"SLDT", "SLWPCB", "SMSW", "SPFLT", "SQRTPD", "SQRTPS", "SQRTSD",
|
||||||
"STAC", "STC", "STD", "STGI", "STI", "STMXCSR", "STOSB", "STOSD",
|
"SQRTSS", "STAC", "STC", "STD", "STGI", "STI", "STMXCSR", "STOSB",
|
||||||
"STOSQ", "STOSW", "STR", "STTILECFG", "STUI", "SUB", "SUBPD",
|
"STOSD", "STOSQ", "STOSW", "STR", "STTILECFG", "STUI", "SUB",
|
||||||
"SUBPS", "SUBSD", "SUBSS", "SVDC", "SVLDT", "SVTS", "SWAPGS",
|
"SUBPD", "SUBPS", "SUBSD", "SUBSS", "SWAPGS", "SYSCALL", "SYSENTER",
|
||||||
"SYSCALL", "SYSENTER", "SYSEXIT", "SYSRET", "T1MSKC", "TCMMIMFP16PS",
|
"SYSEXIT", "SYSRET", "T1MSKC", "TCMMIMFP16PS", "TCMMRLFP16PS",
|
||||||
"TCMMRLFP16PS", "TDCALL", "TDPBF16PS", "TDPBSSD", "TDPBSUD",
|
"TDCALL", "TDPBF16PS", "TDPBSSD", "TDPBSUD", "TDPBUSD", "TDPBUUD",
|
||||||
"TDPBUSD", "TDPBUUD", "TDPFP16PS", "TEST", "TESTUI", "TILELOADD",
|
"TDPFP16PS", "TEST", "TESTUI", "TILELOADD", "TILELOADDT1", "TILERELEASE",
|
||||||
"TILELOADDT1", "TILERELEASE", "TILESTORED", "TILEZERO", "TLBSYNC",
|
"TILESTORED", "TILEZERO", "TLBSYNC", "TPAUSE", "TZCNT", "TZMSK",
|
||||||
"TPAUSE", "TZCNT", "TZMSK", "UCOMISD", "UCOMISS", "UD0", "UD1",
|
"UCOMISD", "UCOMISS", "UD0", "UD1", "UD2", "UIRET", "UMONITOR",
|
||||||
"UD2", "UIRET", "UMONITOR", "UMWAIT", "UNPCKHPD", "UNPCKHPS",
|
"UMWAIT", "UNPCKHPD", "UNPCKHPS", "UNPCKLPD", "UNPCKLPS", "URDMSR",
|
||||||
"UNPCKLPD", "UNPCKLPS", "V4FMADDPS", "V4FMADDSS", "V4FNMADDPS",
|
"UWRMSR", "V4FMADDPS", "V4FMADDSS", "V4FNMADDPS", "V4FNMADDSS",
|
||||||
"V4FNMADDSS", "VADDPD", "VADDPH", "VADDPS", "VADDSD", "VADDSH",
|
"VADDPD", "VADDPH", "VADDPS", "VADDSD", "VADDSH", "VADDSS", "VADDSUBPD",
|
||||||
"VADDSS", "VADDSUBPD", "VADDSUBPS", "VAESDEC", "VAESDECLAST",
|
"VADDSUBPS", "VAESDEC", "VAESDECLAST", "VAESENC", "VAESENCLAST",
|
||||||
"VAESENC", "VAESENCLAST", "VAESIMC", "VAESKEYGENASSIST", "VALIGND",
|
"VAESIMC", "VAESKEYGENASSIST", "VALIGND", "VALIGNQ", "VANDNPD",
|
||||||
"VALIGNQ", "VANDNPD", "VANDNPS", "VANDPD", "VANDPS", "VBCSTNEBF162PS",
|
"VANDNPS", "VANDPD", "VANDPS", "VBCSTNEBF162PS", "VBCSTNESH2PS",
|
||||||
"VBCSTNESH2PS", "VBLENDMPD", "VBLENDMPS", "VBLENDPD", "VBLENDPS",
|
"VBLENDMPD", "VBLENDMPS", "VBLENDPD", "VBLENDPS", "VBLENDVPD",
|
||||||
"VBLENDVPD", "VBLENDVPS", "VBROADCASTF128", "VBROADCASTF32X2",
|
"VBLENDVPS", "VBROADCASTF128", "VBROADCASTF32X2", "VBROADCASTF32X4",
|
||||||
"VBROADCASTF32X4", "VBROADCASTF32X8", "VBROADCASTF64X2", "VBROADCASTF64X4",
|
"VBROADCASTF32X8", "VBROADCASTF64X2", "VBROADCASTF64X4", "VBROADCASTI128",
|
||||||
"VBROADCASTI128", "VBROADCASTI32X2", "VBROADCASTI32X4", "VBROADCASTI32X8",
|
"VBROADCASTI32X2", "VBROADCASTI32X4", "VBROADCASTI32X8", "VBROADCASTI64X2",
|
||||||
"VBROADCASTI64X2", "VBROADCASTI64X4", "VBROADCASTSD", "VBROADCASTSS",
|
"VBROADCASTI64X4", "VBROADCASTSD", "VBROADCASTSS", "VCMPPD",
|
||||||
"VCMPPD", "VCMPPH", "VCMPPS", "VCMPSD", "VCMPSH", "VCMPSS", "VCOMISD",
|
"VCMPPH", "VCMPPS", "VCMPSD", "VCMPSH", "VCMPSS", "VCOMISD",
|
||||||
"VCOMISH", "VCOMISS", "VCOMPRESSPD", "VCOMPRESSPS", "VCVTDQ2PD",
|
"VCOMISH", "VCOMISS", "VCOMPRESSPD", "VCOMPRESSPS", "VCVTDQ2PD",
|
||||||
"VCVTDQ2PH", "VCVTDQ2PS", "VCVTNE2PS2BF16", "VCVTNEEBF162PS",
|
"VCVTDQ2PH", "VCVTDQ2PS", "VCVTNE2PS2BF16", "VCVTNEEBF162PS",
|
||||||
"VCVTNEEPH2PS", "VCVTNEOBF162PS", "VCVTNEOPH2PS", "VCVTNEPS2BF16",
|
"VCVTNEEPH2PS", "VCVTNEOBF162PS", "VCVTNEOPH2PS", "VCVTNEPS2BF16",
|
||||||
@ -306,13 +313,11 @@ const char *gMnemonics[1751] =
|
|||||||
"VUCOMISH", "VUCOMISS", "VUNPCKHPD", "VUNPCKHPS", "VUNPCKLPD",
|
"VUCOMISH", "VUCOMISS", "VUNPCKHPD", "VUNPCKHPS", "VUNPCKLPD",
|
||||||
"VUNPCKLPS", "VXORPD", "VXORPS", "VZEROALL", "VZEROUPPER", "WAIT",
|
"VUNPCKLPS", "VXORPD", "VXORPS", "VZEROALL", "VZEROUPPER", "WAIT",
|
||||||
"WBINVD", "WBNOINVD", "WRFSBASE", "WRGSBASE", "WRMSR", "WRMSRLIST",
|
"WBINVD", "WBNOINVD", "WRFSBASE", "WRGSBASE", "WRMSR", "WRMSRLIST",
|
||||||
"WRMSRNS", "WRPKRU", "WRSHR", "WRSSD", "WRSSQ", "WRUSSD", "WRUSSQ",
|
"WRMSRNS", "WRPKRU", "WRSSD", "WRSSQ", "WRUSSD", "WRUSSQ", "XABORT",
|
||||||
"XABORT", "XADD", "XBEGIN", "XCHG", "XCRYPTCBC", "XCRYPTCFB",
|
"XADD", "XBEGIN", "XCHG", "XEND", "XGETBV", "XLATB", "XOR", "XORPD",
|
||||||
"XCRYPTCTR", "XCRYPTECB", "XCRYPTOFB", "XEND", "XGETBV", "XLATB",
|
"XORPS", "XRESLDTRK", "XRSTOR", "XRSTOR64", "XRSTORS", "XRSTORS64",
|
||||||
"XOR", "XORPD", "XORPS", "XRESLDTRK", "XRSTOR", "XRSTOR64", "XRSTORS",
|
"XSAVE", "XSAVE64", "XSAVEC", "XSAVEC64", "XSAVEOPT", "XSAVEOPT64",
|
||||||
"XRSTORS64", "XSAVE", "XSAVE64", "XSAVEC", "XSAVEC64", "XSAVEOPT",
|
"XSAVES", "XSAVES64", "XSETBV", "XSUSLDTRK", "XTEST",
|
||||||
"XSAVEOPT64", "XSAVES", "XSAVES64", "XSETBV", "XSHA1", "XSHA256",
|
|
||||||
"XSTORE", "XSUSLDTRK", "XTEST",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#ifndef PREFIXES_H
|
#ifndef BDX86_PREFIXES_H
|
||||||
#define PREFIXES_H
|
#define BDX86_PREFIXES_H
|
||||||
|
|
||||||
#define ND_PREF_CODE_NONE 0
|
#define ND_PREF_CODE_NONE 0
|
||||||
#define ND_PREF_CODE_STANDARD 1
|
#define ND_PREF_CODE_STANDARD 1
|
||||||
@ -26,9 +26,9 @@ static const ND_UINT8 gPrefixesMap[256] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
||||||
0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
||||||
1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
|
1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PREFIXES_H
|
#endif // BDX86_PREFIXES_H
|
38359
bddisasm/include/bdx86_table_evex.h
Normal file
38359
bddisasm/include/bdx86_table_evex.h
Normal file
File diff suppressed because it is too large
Load Diff
16820
bddisasm/include/bdx86_table_root.h
Normal file
16820
bddisasm/include/bdx86_table_root.h
Normal file
File diff suppressed because it is too large
Load Diff
13464
bddisasm/include/bdx86_table_vex.h
Normal file
13464
bddisasm/include/bdx86_table_vex.h
Normal file
File diff suppressed because it is too large
Load Diff
1557
bddisasm/include/bdx86_table_xop.h
Normal file
1557
bddisasm/include/bdx86_table_xop.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,10 +2,10 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#ifndef TABLEDEFS_H
|
#ifndef BDX86_TABLEDEFS_H
|
||||||
#define TABLEDEFS_H
|
#define BDX86_TABLEDEFS_H
|
||||||
|
|
||||||
#include "../inc/disasmtypes.h"
|
#include "../inc/bddisasm_types.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Types of tables.
|
// Types of tables.
|
||||||
@ -14,27 +14,29 @@ typedef enum _ND_ILUT_TYPE
|
|||||||
{
|
{
|
||||||
ND_ILUT_INSTRUCTION = 0,// Table contains one entry that directly points to an instruction.
|
ND_ILUT_INSTRUCTION = 0,// Table contains one entry that directly points to an instruction.
|
||||||
ND_ILUT_OPCODE, // Table contains 256 entries. Next entry is selected using an opcode.
|
ND_ILUT_OPCODE, // Table contains 256 entries. Next entry is selected using an opcode.
|
||||||
ND_ILUT_OPCODE_3DNOW, // Table contains 256 entries. Next entry is selected using an opcode, but the
|
ND_ILUT_OPCODE_LAST, // Table contains 256 entries. Next entry is selected using an opcode, but the
|
||||||
// opcode follows the instruction.
|
// opcode follows the instruction as the last byte.
|
||||||
ND_ILUT_MODRM_MOD, // Table contains 2 entries. Next entry is selected using modrm.mod (0 - mem, 1 - reg)
|
|
||||||
ND_ILUT_MODRM_REG, // Table contains 8 entries. Next entry is selected using modrm.reg.
|
ND_ILUT_MODRM_REG, // Table contains 8 entries. Next entry is selected using modrm.reg.
|
||||||
|
ND_ILUT_MODRM_MOD, // Table contains 2 entries. Next entry is selected using modrm.mod (0 - mem, 1 - reg)
|
||||||
ND_ILUT_MODRM_RM, // Table contains 8 entries. Next entry is selected using modrm.rm.
|
ND_ILUT_MODRM_RM, // Table contains 8 entries. Next entry is selected using modrm.rm.
|
||||||
ND_ILUT_MAN_PREFIX, // Table contains 4 entries. Next entry is 0 (no prefix), 1 (0x66), 2 (0xF3), 3 (0xF2).
|
ND_ILUT_MAN_PREFIX, // Table contains 4 entries. Next entry is 0 (no prefix), 1 (0x66), 2 (0xF3), 3 (0xF2).
|
||||||
ND_ILUT_MODE, // Table contains 4 entries. Next entry is 0 (16 bit mode), 1 (32 bit mode), 2 (64 bit mode).
|
ND_ILUT_MODE, // Table contains 4 entries. Next entry is 0 (16 bit mode), 1 (32 bit mode), 2 (64 bit mode).
|
||||||
ND_ILUT_DSIZE, // Table contains 4 entries. Next entry is 0 (16 bit size), 1 (32 bit size), 2 (64 bit size).
|
ND_ILUT_DSIZE, // Table contains 4 entries. Next entry is 0 (16 bit size), 1 (32 bit size), 2 (64 bit size).
|
||||||
// This DOES NOT take into consideration forced/default sizes.
|
// This DOES NOT take into consideration forced/default sizes.
|
||||||
ND_ILUT_ASIZE, // Default addressing mode is used to transition
|
ND_ILUT_ASIZE, // Default addressing mode is used to transition
|
||||||
ND_ILUT_AUXILIARY, // Table contains 8 entries. Next entry is 0 (no prefix), 1 (rex), 2 (rex.w), 3 (64 bit),
|
ND_ILUT_AUXILIARY, // Table contains 10 entries. Next entry is 0 (no prefix), 1 (rex), 2 (rex.w), etc.
|
||||||
// 4 (default op size 16), 5 (default op size 32), 6 (default op size 64),
|
|
||||||
ND_ILUT_VENDOR, // Preferred vendor is used to transition. Default is entry 0. Otherwise, preferred
|
ND_ILUT_VENDOR, // Preferred vendor is used to transition. Default is entry 0. Otherwise, preferred
|
||||||
// vendor selects an alternate entry.
|
// vendor selects an alternate entry.
|
||||||
ND_ILUT_FEATURE, // Some instructions are mapped onto wide NOP space. They will be decoded only if the
|
ND_ILUT_FEATURE, // Some instructions are mapped onto wide NOP space. They will be decoded only if the
|
||||||
// associated feature is set during decoding.
|
// associated feature is set during decoding.
|
||||||
ND_ILUT_VEX_MMMMM, // Table contains 32 entries. Next entry is vex/xop/evex.mmmmm
|
ND_ILUT_EX_M, // Table contains 32 entries. Next entry is vex/xop/evex.mmmmm
|
||||||
ND_ILUT_VEX_PP, // Table contains 4 entries. Next entry is vex/xop/evex.pp
|
ND_ILUT_EX_PP, // Table contains 4 entries. Next entry is vex/xop/evex.pp
|
||||||
ND_ILUT_VEX_L, // Table contains 4 entries. Next entry is vex/xop.l or evex.l'l
|
ND_ILUT_EX_L, // Table contains 4 entries. Next entry is vex/xop.l or evex.l'l
|
||||||
ND_ILUT_VEX_W, // Table contains 2 entries. Next entry is vex/xop/evex.w
|
ND_ILUT_EX_W, // Table contains 2 entries. Next entry is vex/xop/evex.w
|
||||||
ND_ILUT_VEX_WI, // Table contains 2 entries. Next entry is vex/xop/evex.w. If not in 64 bit, next entry is 0.
|
ND_ILUT_EX_WI, // Table contains 2 entries. Next entry is vex/xop/evex.w. If not in 64 bit, next entry is 0.
|
||||||
|
ND_ILUT_EX_ND, // Table contains 2 entries. Next entry is evex.ND.
|
||||||
|
ND_ILUT_EX_NF, // Table contains 2 entries. Next entry is evex.NF.
|
||||||
|
ND_ILUT_EX_SC, // Table contains 16 entries. Next entry is evex.SC.
|
||||||
} ND_ILUT_TYPE;
|
} ND_ILUT_TYPE;
|
||||||
|
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ typedef enum _ND_ILUT_TYPE
|
|||||||
#define ND_ILUT_INDEX_MOD_REG 1
|
#define ND_ILUT_INDEX_MOD_REG 1
|
||||||
|
|
||||||
// Mandatory prefixes.
|
// Mandatory prefixes.
|
||||||
#define ND_ILUT_INDEX_MAN_PREF_NONE 0
|
#define ND_ILUT_INDEX_MAN_PREF_NP 0
|
||||||
#define ND_ILUT_INDEX_MAN_PREF_66 1
|
#define ND_ILUT_INDEX_MAN_PREF_66 1
|
||||||
#define ND_ILUT_INDEX_MAN_PREF_F3 2
|
#define ND_ILUT_INDEX_MAN_PREF_F3 2
|
||||||
#define ND_ILUT_INDEX_MAN_PREF_F2 3
|
#define ND_ILUT_INDEX_MAN_PREF_F2 3
|
||||||
@ -72,10 +74,12 @@ typedef enum _ND_ILUT_TYPE
|
|||||||
#define ND_ILUT_INDEX_AUX_NONE 0
|
#define ND_ILUT_INDEX_AUX_NONE 0
|
||||||
#define ND_ILUT_INDEX_AUX_REXB 1
|
#define ND_ILUT_INDEX_AUX_REXB 1
|
||||||
#define ND_ILUT_INDEX_AUX_REXW 2
|
#define ND_ILUT_INDEX_AUX_REXW 2
|
||||||
#define ND_ILUT_INDEX_AUX_O64 3
|
#define ND_ILUT_INDEX_AUX_MO64 3
|
||||||
#define ND_ILUT_INDEX_AUX_F3 4
|
#define ND_ILUT_INDEX_AUX_REPZ 4
|
||||||
#define ND_ILUT_INDEX_AUX_REP 5
|
#define ND_ILUT_INDEX_AUX_REP 5
|
||||||
#define ND_ILUT_INDEX_AUX_RIPREL 6
|
#define ND_ILUT_INDEX_AUX_RIPREL 6
|
||||||
|
#define ND_ILUT_INDEX_AUX_REX2 7
|
||||||
|
#define ND_ILUT_INDEX_AUX_REX2W 8
|
||||||
|
|
||||||
// Specific features for instructions that map on the wide NOP space.
|
// Specific features for instructions that map on the wide NOP space.
|
||||||
#define ND_ILUT_FEATURE_NONE 0
|
#define ND_ILUT_FEATURE_NONE 0
|
||||||
@ -85,9 +89,6 @@ typedef enum _ND_ILUT_TYPE
|
|||||||
#define ND_ILUT_FEATURE_PITI 4
|
#define ND_ILUT_FEATURE_PITI 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _ND_TABLE
|
typedef struct _ND_TABLE
|
||||||
{
|
{
|
||||||
ND_UINT32 Type;
|
ND_UINT32 Type;
|
||||||
@ -130,11 +131,10 @@ typedef struct _ND_TABLE_MPREFIX
|
|||||||
const void *Table[4];
|
const void *Table[4];
|
||||||
} ND_TABLE_MPREFIX, *PND_TABLE_MPREFIX;
|
} ND_TABLE_MPREFIX, *PND_TABLE_MPREFIX;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _ND_TABLE_AUXILIARY
|
typedef struct _ND_TABLE_AUXILIARY
|
||||||
{
|
{
|
||||||
ND_UINT32 Type;
|
ND_UINT32 Type;
|
||||||
const void *Table[8];
|
const void *Table[10];
|
||||||
} ND_TABLE_AUXILIARY, *PND_TABLE_AUXILIARY;
|
} ND_TABLE_AUXILIARY, *PND_TABLE_AUXILIARY;
|
||||||
|
|
||||||
typedef struct _ND_TABLE_VENDOR
|
typedef struct _ND_TABLE_VENDOR
|
||||||
@ -167,65 +167,66 @@ typedef struct _ND_TABLE_MODE
|
|||||||
const void *Table[4];
|
const void *Table[4];
|
||||||
} ND_TABLE_MODE, *PND_TABLE_MODE;
|
} ND_TABLE_MODE, *PND_TABLE_MODE;
|
||||||
|
|
||||||
typedef struct _ND_TABLE_VEX_MMMMM
|
typedef struct _ND_TABLE_EX_M
|
||||||
{
|
{
|
||||||
ND_UINT32 Type;
|
ND_UINT32 Type;
|
||||||
const void *Table[32];
|
const void *Table[32];
|
||||||
} ND_TABLE_VEX_MMMMM, *PND_TABLE_VEX_MMMMM;
|
} ND_TABLE_EX_M, *PND_TABLE_EX_M;
|
||||||
|
|
||||||
typedef struct _ND_TABLE_VEX_PP
|
typedef struct _ND_TABLE_EX_PP
|
||||||
{
|
{
|
||||||
ND_UINT32 Type;
|
ND_UINT32 Type;
|
||||||
const void *Table[4];
|
const void *Table[4];
|
||||||
} ND_TABLE_VEX_PP, *PND_TABLE_VEX_PP;
|
} ND_TABLE_EX_PP, *PND_TABLE_EX_PP;
|
||||||
|
|
||||||
typedef struct _ND_TABLE_VEX_L
|
typedef struct _ND_TABLE_EX_L
|
||||||
{
|
{
|
||||||
ND_UINT32 Type;
|
ND_UINT32 Type;
|
||||||
const void *Table[4];
|
const void *Table[4];
|
||||||
} ND_TABLE_VEX_L, *PND_TABLE_VEX_L;
|
} ND_TABLE_EX_L, *PND_TABLE_EX_L;
|
||||||
|
|
||||||
typedef struct _ND_TABLE_VEX_W
|
typedef struct _ND_TABLE_EX_W
|
||||||
{
|
{
|
||||||
ND_UINT32 Type;
|
ND_UINT32 Type;
|
||||||
const void *Table[8];
|
const void *Table[2];
|
||||||
} ND_TABLE_VEX_W, *PND_TABLE_VEX_W;
|
} ND_TABLE_EX_W, *PND_TABLE_EX_W;
|
||||||
|
|
||||||
|
typedef struct _ND_TABLE_EX_ND
|
||||||
|
{
|
||||||
|
ND_UINT32 Type;
|
||||||
|
const void *Table[2];
|
||||||
|
} ND_TABLE_EX_ND, *PND_TABLE_EX_ND;
|
||||||
|
|
||||||
|
typedef struct _ND_TABLE_EX_NF
|
||||||
|
{
|
||||||
|
ND_UINT32 Type;
|
||||||
|
const void *Table[2];
|
||||||
|
} ND_TABLE_EX_NF, *PND_TABLE_EX_NF;
|
||||||
|
|
||||||
|
typedef struct _ND_TABLE_EX_SC
|
||||||
|
{
|
||||||
|
ND_UINT32 Type;
|
||||||
|
const void *Table[16];
|
||||||
|
} ND_TABLE_EX_SC, *PND_TABLE_EX_SC;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// One instruction entry. This structure should be maintained bellow 2 cache lines in size (128 bytes).
|
// One instruction database entry.
|
||||||
//
|
//
|
||||||
#ifdef _MSC_VER
|
typedef struct _ND_IDBE
|
||||||
__declspec(align(128))
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4214)
|
|
||||||
#else
|
|
||||||
__attribute__((aligned(128)))
|
|
||||||
#endif
|
|
||||||
typedef struct _ND_INSTRUCTION
|
|
||||||
{
|
{
|
||||||
ND_UINT16 Instruction; // Instruction identifier. Check ND_INS_CLASS definitions.
|
ND_UINT16 Instruction; // Instruction identifier. Check ND_INS_CLASS definitions.
|
||||||
ND_UINT8 Category; // Instruction category. Check ND_INS_TYPE.
|
ND_UINT8 Category; // Instruction category. Check ND_INS_TYPE.
|
||||||
ND_UINT8 IsaSet; // Instruction set. Check ND_INS_SET.
|
ND_UINT8 IsaSet; // Instruction set. Check ND_INS_SET.
|
||||||
ND_UINT16 Mnemonic; // Mnemonic (index inside the global mnemonic table).
|
ND_UINT16 Mnemonic; // Mnemonic (index inside the global mnemonic table).
|
||||||
|
|
||||||
ND_UINT16 ValidPrefixes; // Accepted prefixes.
|
ND_UINT16 ValidPrefixes; // Accepted prefixes.
|
||||||
ND_UINT32 ValidModes; // Valid operating modes for the instruction.
|
ND_UINT32 ValidModes; // Valid operating modes for the instruction.
|
||||||
ND_UINT8 ValidDecorators;// Accepted decorators (valid for EVEX instructions).
|
ND_UINT8 ValidDecorators;// Accepted decorators (valid for EVEX instructions).
|
||||||
|
|
||||||
ND_UINT8 OpsCount; // Low 4 bits: explicit operands count; high 4 bits: implicit ops count.
|
ND_UINT8 OpsCount; // Low 4 bits: explicit operands count; high 4 bits: implicit ops count.
|
||||||
|
|
||||||
ND_UINT8 TupleType; // EVEX tuple type.
|
ND_UINT8 TupleType; // EVEX tuple type.
|
||||||
ND_UINT8 ExcType : 5; // SSE/VEX/EVEX/OPMASK/AMX exception type.
|
ND_UINT8 ExcType; // SSE/VEX/EVEX/OPMASK/AMX/APX exception type.
|
||||||
ND_UINT8 ExcClass : 3; // Indicates the exception class (SSE/AVX, EVEX, OPMASK or AMX).
|
|
||||||
|
|
||||||
ND_UINT8 FpuFlags; // FPU status word C0, C1, C2 & C3 access type.
|
ND_UINT8 FpuFlags; // FPU status word C0, C1, C2 & C3 access type.
|
||||||
|
ND_UINT8 EvexMode; // EVEX prefix extension type.
|
||||||
ND_UINT8 Reserved2;
|
|
||||||
ND_UINT16 Reserved3;
|
|
||||||
|
|
||||||
ND_UINT32 Attributes; // Instruction attributes.
|
|
||||||
ND_UINT64 CpuidFlag; // Required CPUID feature flag.
|
|
||||||
|
|
||||||
// Per-flag access. Undefined flags will have their bit set in both the "Set" and "Cleared" mask, since a flag
|
// Per-flag access. Undefined flags will have their bit set in both the "Set" and "Cleared" mask, since a flag
|
||||||
// cannot be both cleared and set.
|
// cannot be both cleared and set.
|
||||||
@ -234,11 +235,14 @@ typedef struct _ND_INSTRUCTION
|
|||||||
ND_UINT32 SetFlags; // Flags that are always set to 1.
|
ND_UINT32 SetFlags; // Flags that are always set to 1.
|
||||||
ND_UINT32 ClearedFlags; // Flags that are always cleared.
|
ND_UINT32 ClearedFlags; // Flags that are always cleared.
|
||||||
|
|
||||||
|
ND_UINT64 Attributes; // Instruction attributes.
|
||||||
|
ND_UINT64 CpuidFlag; // Required CPUID feature flag.
|
||||||
|
|
||||||
|
// List of operands. Up to 10 implicit and explicit operands stored in DB.
|
||||||
ND_UINT64 Operands[10];
|
ND_UINT64 Operands[10];
|
||||||
} ND_INSTRUCTION, *PND_INSTRUCTION;
|
|
||||||
#ifdef _MSC_VER
|
} ND_IDBE, *PND_IDBE;
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following definitions are per-operand specific.
|
// The following definitions are per-operand specific.
|
||||||
@ -376,7 +380,6 @@ typedef enum _ND_OPERAND_TYPE_SPEC
|
|||||||
ND_OPT_I,
|
ND_OPT_I,
|
||||||
ND_OPT_J,
|
ND_OPT_J,
|
||||||
ND_OPT_K,
|
ND_OPT_K,
|
||||||
|
|
||||||
ND_OPT_L,
|
ND_OPT_L,
|
||||||
ND_OPT_M,
|
ND_OPT_M,
|
||||||
ND_OPT_N,
|
ND_OPT_N,
|
||||||
@ -387,7 +390,6 @@ typedef enum _ND_OPERAND_TYPE_SPEC
|
|||||||
ND_OPT_S,
|
ND_OPT_S,
|
||||||
ND_OPT_T,
|
ND_OPT_T,
|
||||||
ND_OPT_U,
|
ND_OPT_U,
|
||||||
|
|
||||||
ND_OPT_V,
|
ND_OPT_V,
|
||||||
ND_OPT_W,
|
ND_OPT_W,
|
||||||
ND_OPT_X,
|
ND_OPT_X,
|
||||||
@ -404,91 +406,92 @@ typedef enum _ND_OPERAND_TYPE_SPEC
|
|||||||
ND_OPT_rT,
|
ND_OPT_rT,
|
||||||
ND_OPT_mT,
|
ND_OPT_mT,
|
||||||
ND_OPT_vT,
|
ND_OPT_vT,
|
||||||
ND_OPT_CONST_1,
|
ND_OPT_dfv,
|
||||||
|
ND_OPT_1,
|
||||||
|
|
||||||
// These are implicit arguments inside instructions.
|
// These are implicit arguments inside instructions.
|
||||||
|
|
||||||
// Special registers.
|
// Special registers.
|
||||||
ND_OPT_RIP,
|
ND_OPT_rIP,
|
||||||
ND_OPT_MXCSR,
|
ND_OPT_MXCSR,
|
||||||
ND_OPT_PKRU,
|
ND_OPT_PKRU,
|
||||||
ND_OPT_SSP,
|
ND_OPT_SSP,
|
||||||
ND_OPT_UIF,
|
ND_OPT_UIF,
|
||||||
|
|
||||||
// General Purpose REgisters.
|
// General Purpose REgisters.
|
||||||
ND_OPT_GPR_AH,
|
ND_OPT_AH,
|
||||||
ND_OPT_GPR_rAX,
|
ND_OPT_rAX,
|
||||||
ND_OPT_GPR_rCX,
|
ND_OPT_rCX,
|
||||||
ND_OPT_GPR_rDX,
|
ND_OPT_rDX,
|
||||||
ND_OPT_GPR_rBX,
|
ND_OPT_rBX,
|
||||||
ND_OPT_GPR_rSP,
|
ND_OPT_rSP,
|
||||||
ND_OPT_GPR_rBP,
|
ND_OPT_rBP,
|
||||||
ND_OPT_GPR_rSI,
|
ND_OPT_rSI,
|
||||||
ND_OPT_GPR_rDI,
|
ND_OPT_rDI,
|
||||||
ND_OPT_GPR_rR8,
|
ND_OPT_rR8,
|
||||||
ND_OPT_GPR_rR9,
|
ND_OPT_rR9,
|
||||||
ND_OPT_GPR_rR11,
|
ND_OPT_rR11,
|
||||||
|
|
||||||
// Segment registers.
|
// Segment registers.
|
||||||
ND_OPT_SEG_CS,
|
ND_OPT_CS,
|
||||||
ND_OPT_SEG_SS,
|
ND_OPT_SS,
|
||||||
ND_OPT_SEG_DS,
|
ND_OPT_DS,
|
||||||
ND_OPT_SEG_ES,
|
ND_OPT_ES,
|
||||||
ND_OPT_SEG_FS,
|
ND_OPT_FS,
|
||||||
ND_OPT_SEG_GS,
|
ND_OPT_GS,
|
||||||
|
|
||||||
// FPU registers.
|
// FPU registers.
|
||||||
ND_OPT_FPU_ST0,
|
ND_OPT_ST0,
|
||||||
ND_OPT_FPU_STX,
|
ND_OPT_STi,
|
||||||
|
|
||||||
// SSE registers.
|
// SSE registers.
|
||||||
ND_OPT_SSE_XMM0,
|
ND_OPT_XMM0,
|
||||||
ND_OPT_SSE_XMM1,
|
ND_OPT_XMM1,
|
||||||
ND_OPT_SSE_XMM2,
|
ND_OPT_XMM2,
|
||||||
ND_OPT_SSE_XMM3,
|
ND_OPT_XMM3,
|
||||||
ND_OPT_SSE_XMM4,
|
ND_OPT_XMM4,
|
||||||
ND_OPT_SSE_XMM5,
|
ND_OPT_XMM5,
|
||||||
ND_OPT_SSE_XMM6,
|
ND_OPT_XMM6,
|
||||||
ND_OPT_SSE_XMM7,
|
ND_OPT_XMM7,
|
||||||
|
|
||||||
// Implicit memory operands.
|
// Implicit memory operands.
|
||||||
ND_OPT_MEM_rAX, // [rAX]
|
ND_OPT_pAX, // [rAX]
|
||||||
ND_OPT_MEM_rCX, // [rCX]
|
ND_OPT_pCX, // [rCX]
|
||||||
ND_OPT_MEM_rBX_AL, // [rBX + AL]
|
ND_OPT_pBXAL, // [rBX + AL]
|
||||||
ND_OPT_MEM_rDI, // [rDI]
|
ND_OPT_pDI, // [rDI]
|
||||||
ND_OPT_MEM_SHS, // Shadow stack.
|
ND_OPT_SHS, // Shadow stack.
|
||||||
ND_OPT_MEM_SHSP, // Shadow stack pointed by the SSP.
|
ND_OPT_SHSP, // Shadow stack pointed by the SSP.
|
||||||
ND_OPT_MEM_SHS0,
|
ND_OPT_SHS0, // Shadow stack pointed by the SSP.
|
||||||
ND_OPT_MEM_SMSRT, // Source MSR table, encoded in [RSI].
|
ND_OPT_SMT, // Source MSR table, encoded in [RSI].
|
||||||
ND_OPT_MEM_DMSRT, // Destination MSR table, encoded in [RDI].
|
ND_OPT_DMT, // Destination MSR table, encoded in [RDI].
|
||||||
|
|
||||||
// Special immediates.
|
// Special immediates.
|
||||||
ND_OPT_Im2z,
|
ND_OPT_m2zI,
|
||||||
|
|
||||||
// Misc CR/XCR/MSR/SYS registers.
|
// Misc CR/XCR/MSR/SYS registers.
|
||||||
ND_OPT_CR_0,
|
ND_OPT_CR0,
|
||||||
ND_OPT_SYS_IDTR,
|
ND_OPT_IDTR,
|
||||||
ND_OPT_SYS_GDTR,
|
ND_OPT_GDTR,
|
||||||
ND_OPT_SYS_LDTR,
|
ND_OPT_LDTR,
|
||||||
ND_OPT_SYS_TR,
|
ND_OPT_TR,
|
||||||
ND_OPT_X87_CONTROL,
|
ND_OPT_X87CONTROL,
|
||||||
ND_OPT_X87_TAG,
|
ND_OPT_X87TAG,
|
||||||
ND_OPT_X87_STATUS,
|
ND_OPT_X87STATUS,
|
||||||
ND_OPT_MSR,
|
ND_OPT_MSR,
|
||||||
ND_OPT_XCR,
|
ND_OPT_XCR,
|
||||||
ND_OPT_MSR_TSC,
|
ND_OPT_TSC,
|
||||||
ND_OPT_MSR_TSCAUX,
|
ND_OPT_TSCAUX,
|
||||||
ND_OPT_MSR_SEIP,
|
ND_OPT_SEIP,
|
||||||
ND_OPT_MSR_SESP,
|
ND_OPT_SESP,
|
||||||
ND_OPT_MSR_SCS,
|
ND_OPT_SCS,
|
||||||
ND_OPT_MSR_STAR,
|
ND_OPT_STAR,
|
||||||
ND_OPT_MSR_LSTAR,
|
ND_OPT_LSTAR,
|
||||||
ND_OPT_MSR_FMASK,
|
ND_OPT_FMASK,
|
||||||
ND_OPT_MSR_FSBASE,
|
ND_OPT_FSBASE,
|
||||||
ND_OPT_MSR_GSBASE,
|
ND_OPT_GSBASE,
|
||||||
ND_OPT_MSR_KGSBASE,
|
ND_OPT_KGSBASE,
|
||||||
ND_OPT_XCR_0,
|
ND_OPT_XCR0,
|
||||||
ND_OPT_REG_BANK,
|
ND_OPT_BANK,
|
||||||
|
|
||||||
} ND_OPERAND_TYPE_SPEC;
|
} ND_OPERAND_TYPE_SPEC;
|
||||||
|
|
||||||
@ -496,9 +499,9 @@ typedef enum _ND_OPERAND_TYPE_SPEC
|
|||||||
//
|
//
|
||||||
// Operand flags.
|
// Operand flags.
|
||||||
//
|
//
|
||||||
#define ND_OPF_DEFAULT 0x01 // The operand is default, no need to show it in disassembly.
|
#define ND_OPF_OPDEF 0x01 // The operand is default, no need to show it in disassembly.
|
||||||
#define ND_OPF_SEX_OP1 0x02 // The operand is sign-extended to the first operands' size.
|
#define ND_OPF_OPSIGNEXO1 0x02 // The operand is sign-extended to the first operands' size.
|
||||||
#define ND_OPF_SEX_DWS 0x04 // The operand is sign-extended to the default word size.
|
#define ND_OPF_OPSIGNEXDW 0x04 // The operand is sign-extended to the default word size.
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -520,7 +523,7 @@ typedef enum _ND_OPERAND_TYPE_SPEC
|
|||||||
// Operand decorator flags.
|
// Operand decorator flags.
|
||||||
//
|
//
|
||||||
#define ND_OPD_MASK 0x01 // Mask accepted.
|
#define ND_OPD_MASK 0x01 // Mask accepted.
|
||||||
#define ND_OPD_Z 0x02 // Zeroing accepted.
|
#define ND_OPD_ZERO 0x02 // Zeroing accepted.
|
||||||
#define ND_OPD_B32 0x04 // 32 bit broadcast supported.
|
#define ND_OPD_B32 0x04 // 32 bit broadcast supported.
|
||||||
#define ND_OPD_B64 0x08 // 64 bit broadcast supported.
|
#define ND_OPD_B64 0x08 // 64 bit broadcast supported.
|
||||||
#define ND_OPD_SAE 0x10 // Suppress all exceptions supported.
|
#define ND_OPD_SAE 0x10 // Suppress all exceptions supported.
|
||||||
@ -533,13 +536,13 @@ typedef enum _ND_OPERAND_TYPE_SPEC
|
|||||||
//
|
//
|
||||||
// Include auto-generated stuff.
|
// Include auto-generated stuff.
|
||||||
//
|
//
|
||||||
#include "mnemonics.h"
|
#include "../../inc/bdx86_constants.h"
|
||||||
#include "../../inc/constants.h"
|
#include "bdx86_mnemonics.h"
|
||||||
#include "instructions.h"
|
#include "bdx86_instructions.h"
|
||||||
#include "prefixes.h"
|
#include "bdx86_prefixes.h"
|
||||||
#include "table_root.h"
|
#include "bdx86_table_root.h"
|
||||||
#include "table_xop.h"
|
#include "bdx86_table_xop.h"
|
||||||
#include "table_vex.h"
|
#include "bdx86_table_vex.h"
|
||||||
#include "table_evex.h"
|
#include "bdx86_table_evex.h"
|
||||||
|
|
||||||
#endif // TABLEDEFS_H
|
#endif // BDX86_TABLEDEFS_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
# Disassembler Tests
|
# Disassembler Tests
|
||||||
|
|
||||||
These tests are used to validate bddisasm. Each test consists of up to three files:
|
These tests are used to validate bddisasm. Each test consists of up to three files:
|
||||||
* The binary test file. The name format for this type of file is `name_16|32|64`. No extension must be provided; 16/32/64 indicates disassembly mode
|
* The binary test file. The name format for this type of file is `name_16|32|64.test`. 16/32/64 indicates disassembly mode
|
||||||
* The output result file. Must be named the same as the binary test file, but with the extension .result
|
* The output result file. Must be named the same as the binary test file, but with the extension .result
|
||||||
* Optional assembly file, used to generate the binary test file
|
* Optional assembly file, used to generate the binary test file
|
||||||
|
|
||||||
|
102913
bddisasm_test/x86/apx/apx1_64.result
Normal file
102913
bddisasm_test/x86/apx/apx1_64.result
Normal file
File diff suppressed because it is too large
Load Diff
BIN
bddisasm_test/x86/apx/apx1_64.test
Normal file
BIN
bddisasm_test/x86/apx/apx1_64.test
Normal file
Binary file not shown.
224
bddisasm_test/x86/apx/apx2_64.result
Normal file
224
bddisasm_test/x86/apx/apx2_64.result
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
0000000000000000 626c7808fc1e AADD dword ptr [r22], r27d
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000006 626cf808fc1e AADD qword ptr [r22], r27
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
000000000000000C 626c7908fc1e AAND dword ptr [r22], r27d
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000012 626cf908fc1e AAND qword ptr [r22], r27
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000018 626c7b08fc1e AOR dword ptr [r22], r27d
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
000000000000001E 626cfb08fc1e AOR qword ptr [r22], r27
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000024 626c7a08fc1e AXOR dword ptr [r22], r27d
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
000000000000002A 626cfa08fc1e AXOR qword ptr [r22], r27
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||||
|
Segment: 3, Base: 22,
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000030 626c7b08f8de URDMSR r22, r27
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-USER-MSR
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000036 62ff7b08f8c6bdbdbdbd URDMSR r22, 0xbdbdbdbd
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||||
|
Operand: 2, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000040 626c7a08f8de UWRMSR r27, r22
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Exception class: APX, exception type: APX-EVEX-USER-MSR
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000046 62ff7a08f8c6bdbdbdbd UWRMSR 0xbdbdbdbd, r22
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
EVEX Tuple Type: None
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||||
|
|
1
bddisasm_test/x86/apx/apx2_64.test
Normal file
1
bddisasm_test/x86/apx/apx2_64.test
Normal file
@ -0,0 +1 @@
|
|||||||
|
blxüblřüblyüblůübl{üblűüblzüblúübl{řŢb˙{řĆ˝˝˝˝blzřŢb˙zřĆ˝˝˝˝
|
16
bddisasm_test/x86/apx/evex_bad_64_skip.asm
Normal file
16
bddisasm_test/x86/apx/evex_bad_64_skip.asm
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
bits 64
|
||||||
|
|
||||||
|
; NF not supported.
|
||||||
|
db 0x62, 0x6C, 0x78, 0x0C, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
; V' set.
|
||||||
|
db 0x62, 0x6C, 0x78, 0x00, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
; VVVV set.
|
||||||
|
db 0x62, 0x6C, 0x38, 0x08, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
; Reserved bits set.
|
||||||
|
db 0x62, 0x6C, 0x78, 0x09, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
db 0x62, 0x6C, 0x78, 0x88, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
; Invalid PUSH2 register (RSP).
|
||||||
|
db 0x62, 0x6C, 0x58, 0x18, 0xFF, 0xF4, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
; Invalid POP2 registers (same dest register, RAX).
|
||||||
|
db 0x62, 0x64, 0x78, 0x18, 0x8F, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
|
7
bddisasm_test/x86/apx/evex_bad_64_skip.result
Normal file
7
bddisasm_test/x86/apx/evex_bad_64_skip.result
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
0000000000000000 62 db 0x62 (0x80000002)
|
||||||
|
0000000000000010 62 db 0x62 (0x80000040)
|
||||||
|
0000000000000020 62 db 0x62 (0x80000032)
|
||||||
|
0000000000000030 62 db 0x62 (0x80000045)
|
||||||
|
0000000000000040 62 db 0x62 (0x80000045)
|
||||||
|
0000000000000050 62 db 0x62 (0x80000044)
|
||||||
|
0000000000000060 62 db 0x62 (0x80000044)
|
BIN
bddisasm_test/x86/apx/evex_bad_64_skip.test
Normal file
BIN
bddisasm_test/x86/apx/evex_bad_64_skip.test
Normal file
Binary file not shown.
25
bddisasm_test/x86/apx/rex2_bad_64_skip.asm
Normal file
25
bddisasm_test/x86/apx/rex2_bad_64_skip.asm
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
bits 64
|
||||||
|
|
||||||
|
; REX2 with REX
|
||||||
|
db 0x48, 0xD5, 0x00, 0x33, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
; REX with REX2
|
||||||
|
db 0xD5, 0x00, 0x48, 0x33, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
; REX2 with EVEX
|
||||||
|
db 0xD5, 0x00, 0x62, 0x6C, 0x78, 0x08, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
; JMPABS with prefixes
|
||||||
|
db 0x66, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0x67, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0xF2, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0xF3, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||||
|
; REX2 with unssuported instruction
|
||||||
|
db 0xD5, 0x00, 0x70, 0xBD, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0xD5, 0x80, 0x80, 0xBD, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
; REX2 inside legacy map 0x38 & 0x3A
|
||||||
|
db 0xD5, 0x80, 0x38, 0xFC, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0xD5, 0x80, 0x3A, 0xCC, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
; REX2 with extension opcode.
|
||||||
|
db 0xD5, 0x7F, 0x0F, 0xD1, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0xD5, 0x7F, 0x0F, 0x38, 0x00, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
db 0xD5, 0xFF, 0x38, 0x00, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
|
|
||||||
|
|
14
bddisasm_test/x86/apx/rex2_bad_64_skip.result
Normal file
14
bddisasm_test/x86/apx/rex2_bad_64_skip.result
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
0000000000000000 48 db 0x48 (0x80000004)
|
||||||
|
0000000000000010 d5 db 0xd5 (0x80000009)
|
||||||
|
0000000000000020 d5 db 0xd5 (0x80000009)
|
||||||
|
0000000000000030 66 db 0x66 (0x80000002)
|
||||||
|
0000000000000040 67 db 0x67 (0x80000002)
|
||||||
|
0000000000000050 f2 db 0xf2 (0x80000002)
|
||||||
|
0000000000000060 f3 db 0xf3 (0x80000002)
|
||||||
|
0000000000000070 d5 db 0xd5 (0x80000002)
|
||||||
|
0000000000000080 d5 db 0xd5 (0x80000002)
|
||||||
|
0000000000000090 d5 db 0xd5 (0x80000002)
|
||||||
|
00000000000000A0 d5 db 0xd5 (0x80000002)
|
||||||
|
00000000000000B0 d5 db 0xd5 (0x80000002)
|
||||||
|
00000000000000C0 d5 db 0xd5 (0x80000002)
|
||||||
|
00000000000000D0 d5 db 0xd5 (0x80000002)
|
BIN
bddisasm_test/x86/apx/rex2_bad_64_skip.test
Normal file
BIN
bddisasm_test/x86/apx/rex2_bad_64_skip.test
Normal file
Binary file not shown.
32
bddisasm_test/x86/apx/rex2_valid_64.asm
Normal file
32
bddisasm_test/x86/apx/rex2_valid_64.asm
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
bits 64
|
||||||
|
|
||||||
|
; REX2 0
|
||||||
|
db 0xD5, 0x00, 0x33, 0xC0
|
||||||
|
; REX2.W = 1
|
||||||
|
db 0xD5, 0x08, 0x33, 0xC0
|
||||||
|
; REX2.B3 & REX2.B4 set
|
||||||
|
db 0xD5, 0x19, 0x33, 0xC0
|
||||||
|
; REX2.R3 & REX2.R4 set
|
||||||
|
db 0xD5, 0x4C, 0x33, 0xC0
|
||||||
|
; REX2.X3 & REX2.X4 set, no memory
|
||||||
|
db 0xD5, 0x2A, 0x33, 0xC0
|
||||||
|
; REX2.X3 & REX2.X4 set, SIB access
|
||||||
|
db 0xD5, 0x2A, 0x33, 0x04, 0x33
|
||||||
|
; JMPABS
|
||||||
|
db 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD
|
||||||
|
; PUSHP/POPP
|
||||||
|
db 0xD5, 0x08, 0x50
|
||||||
|
db 0xD5, 0x08, 0x58
|
||||||
|
db 0xD5, 0x18, 0x50
|
||||||
|
db 0xD5, 0x18, 0x58
|
||||||
|
; PUSH/POP
|
||||||
|
db 0xD5, 0x00, 0x50
|
||||||
|
db 0xD5, 0x00, 0x58
|
||||||
|
db 0xD5, 0x10, 0x50
|
||||||
|
db 0xD5, 0x10, 0x58
|
||||||
|
; NOP
|
||||||
|
db 0xD5, 0x00, 0x90
|
||||||
|
; XCHG r16, rax
|
||||||
|
db 0xD5, 0x18, 0x90
|
||||||
|
; RDFSBASE r31
|
||||||
|
db 0xF3, 0xD5, 0x99, 0xAE, 0xC7
|
301
bddisasm_test/x86/apx/rex2_valid_64.result
Normal file
301
bddisasm_test/x86/apx/rex2_valid_64.result
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
0000000000000000 d50033c0 XOR eax, eax
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||||
|
FLAGS access
|
||||||
|
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: M, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: Flags, RegSize: 4, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000004 d50833c0 XOR rax, rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||||
|
FLAGS access
|
||||||
|
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000008 d51933c0 XOR rax, r24
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||||
|
FLAGS access
|
||||||
|
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 24, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
000000000000000C d54c33c0 XOR r24, rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||||
|
FLAGS access
|
||||||
|
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 24, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000010 d52a33c0 XOR rax, rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||||
|
FLAGS access
|
||||||
|
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000014 d52a330433 XOR rax, qword ptr [rbx+r30]
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||||
|
FLAGS access
|
||||||
|
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||||
|
Segment: 3, Base: 3, Index: 30 * 1,
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000019 d500a1bdbdbdbdbdbdbdbd JMPABS 0xbdbdbdbdbdbdbdbd
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: UNCOND_BR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Address, Size: 8, RawSize: 8, Encoding: D
|
||||||
|
Operand: 1, Acc: -W, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: IP, RegSize: 4, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000024 d50850 PUSHP rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: PUSH, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
0000000000000027 d50858 POPP rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: POP, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
000000000000002A d51850 PUSHP r16
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: PUSH, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||||
|
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
000000000000002D d51858 POPP r16
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: APX_F, Ins cat: POP, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
0000000000000030 d50050 PUSH rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: PUSH, CET tracked: no
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
0000000000000033 d50058 POP rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: POP, CET tracked: no
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
0000000000000036 d51050 PUSH r16
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: PUSH, CET tracked: no
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||||
|
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
0000000000000039 d51058 POP r16
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: POP, CET tracked: no
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||||
|
Segment: 2, Base: 4,
|
||||||
|
|
||||||
|
000000000000003C d50090 NOP
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: NOP, CET tracked: no
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
|
||||||
|
000000000000003F d51890 XCHG r16, rax
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: I86, Ins cat: DATAXFER, CET tracked: no
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||||
|
Operand: 1, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000042 f3d599aec7 RDFSBASE r31
|
||||||
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: RDWRFSGS, Ins cat: RDWRFSGS, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000000, reg: ebx, bit: 0
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 31, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Model Specific, RegSize: 8, RegId: 0xc0000100, RegCount: 1
|
||||||
|
|
BIN
bddisasm_test/x86/apx/rex2_valid_64.test
Normal file
BIN
bddisasm_test/x86/apx/rex2_valid_64.test
Normal file
Binary file not shown.
@ -2,7 +2,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -24,7 +24,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -46,7 +46,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -68,7 +68,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -90,7 +90,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -112,7 +112,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -134,7 +134,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -156,7 +156,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -178,7 +178,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -200,7 +200,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -222,7 +222,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -244,7 +244,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -266,7 +266,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -288,7 +288,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -310,7 +310,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -332,7 +332,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -354,7 +354,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -376,7 +376,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -398,7 +398,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -420,7 +420,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -442,7 +442,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -464,7 +464,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -486,7 +486,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -508,7 +508,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -530,7 +530,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -552,7 +552,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -574,7 +574,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -596,7 +596,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -618,7 +618,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -640,7 +640,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -662,7 +662,7 @@
|
|||||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
@ -684,7 +684,7 @@
|
|||||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||||
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
ISA Set: CMPCCXADD, Ins cat: CMPCCXADD, CET tracked: no
|
||||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 7
|
||||||
Exception class: EVEX, exception type: E6NF
|
Exception class: SSE/VEX, exception type: 14
|
||||||
FLAGS access
|
FLAGS access
|
||||||
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
CF: m, PF: m, AF: m, ZF: m, SF: m, OF: m,
|
||||||
Valid modes
|
Valid modes
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
REP: no, REPcc: no, LOCK: no
|
REP: no, REPcc: no, LOCK: no
|
||||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
BND: no, BHINT: no, DNT: no
|
BND: no, BHINT: no, DNT: no
|
||||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: IP, RegSize: 8, RegId: 0, RegCount: 1
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Segment, RegSize: 8, RegId: 1, RegCount: 1
|
||||||
Operand: 1, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
Operand: 1, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: IP, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: General Purpose, RegSize: 8, RegId: 4, RegCount: 1
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
Operand: 3, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Segment, RegSize: 8, RegId: 1, RegCount: 1
|
Operand: 3, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Segment, RegSize: 8, RegId: 2, RegCount: 1
|
||||||
Operand: 4, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Segment, RegSize: 8, RegId: 2, RegCount: 1
|
Operand: 4, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: General Purpose, RegSize: 8, RegId: 4, RegCount: 1
|
||||||
Operand: 5, Acc: R-, Type: Memory, Size: 40, RawSize: 40, Encoding: S, Stack: yes,
|
Operand: 5, Acc: R-, Type: Memory, Size: 40, RawSize: 40, Encoding: S, Stack: yes,
|
||||||
Segment: 2, Base: 4,
|
Segment: 2, Base: 4,
|
||||||
Operand: 6, Acc: CRCW, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: SSP, RegSize: 8, RegId: 0, RegCount: 1
|
Operand: 6, Acc: CRCW, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: SSP, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
db 0xD4, 0x90 ; AAM
|
db 0xD4, 0x90 ; AAM
|
||||||
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
db 0xD5, 0x90 ; AAD
|
;db 0xD5, 0x90 ; AAD
|
||||||
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
;db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
db 0x60 ; PUSHA
|
db 0x60 ; PUSHA
|
||||||
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
db 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||||
db 0x61 ; POPA
|
db 0x61 ; POPA
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
0000000000000090 37 db 0x37 (0x80000009)
|
0000000000000090 37 db 0x37 (0x80000009)
|
||||||
00000000000000A0 3f db 0x3f (0x80000009)
|
00000000000000A0 3f db 0x3f (0x80000009)
|
||||||
00000000000000B0 d4 db 0xd4 (0x80000009)
|
00000000000000B0 d4 db 0xd4 (0x80000009)
|
||||||
00000000000000C0 d5 db 0xd5 (0x80000009)
|
00000000000000C0 60 db 0x60 (0x80000009)
|
||||||
00000000000000D0 60 db 0x60 (0x80000009)
|
00000000000000D0 61 db 0x61 (0x80000009)
|
||||||
00000000000000E0 61 db 0x61 (0x80000009)
|
00000000000000E0 9a db 0x9a (0x80000009)
|
||||||
00000000000000F0 9a db 0x9a (0x80000009)
|
00000000000000F0 ea db 0xea (0x80000009)
|
||||||
0000000000000100 ea db 0xea (0x80000009)
|
|
||||||
|
@ -1 +1 @@
|
|||||||
<06><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><07><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><0E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><16><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><17><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><1E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><1F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>7<EFBFBD><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ô<EFBFBD><C394><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>`<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>a<EFBFBD><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>š<EFBFBD><C5A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ê<EFBFBD><C3AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
<06><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><07><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><0E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><16><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><17><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><1E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><1F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>7<EFBFBD><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ô<EFBFBD><C394><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>`<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>a<EFBFBD><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>š<EFBFBD><C5A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ê<EFBFBD><C3AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
11
bddisasm_test/x86/usermsr/rex2_valid_64.asm
Normal file
11
bddisasm_test/x86/usermsr/rex2_valid_64.asm
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
bits 64
|
||||||
|
|
||||||
|
; UWRMSR 0x44332211, rax
|
||||||
|
db 0xC4, 0xE7, 0x7A, 0xF8, 0xC0, 0x11, 0x22, 0x33, 0x44
|
||||||
|
; URDMSR rax, 0x44332211
|
||||||
|
db 0xC4, 0xE7, 0x7B, 0xF8, 0xC0, 0x11, 0x22, 0x33, 0x44
|
||||||
|
; UWRMSR rcx, rax
|
||||||
|
db 0xF3, 0x0F, 0x38, 0xF8, 0xC1
|
||||||
|
; URDMSR rax, rcx
|
||||||
|
db 0xF2, 0x0F, 0x38, 0xF8, 0xC1
|
||||||
|
|
68
bddisasm_test/x86/usermsr/rex2_valid_64.result
Normal file
68
bddisasm_test/x86/usermsr/rex2_valid_64.result
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
0000000000000000 c4e77af8c011223344 UWRMSR 0x44332211, rax
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000009 c4e77bf8c011223344 URDMSR rax, 0x44332211
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||||
|
Operand: 2, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000012 f30f38f8c1 UWRMSR rax, rcx
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 1, RegCount: 1
|
||||||
|
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||||
|
|
||||||
|
0000000000000017 f20f38f8c1 URDMSR rcx, rax
|
||||||
|
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||||
|
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||||
|
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||||
|
Valid modes
|
||||||
|
R0: yes, R1: yes, R2: yes, R3: yes
|
||||||
|
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||||
|
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||||
|
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||||
|
Valid prefixes
|
||||||
|
REP: no, REPcc: no, LOCK: no
|
||||||
|
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||||
|
BND: no, BHINT: no, DNT: no
|
||||||
|
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 1, RegCount: 1
|
||||||
|
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||||
|
Operand: 2, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||||
|
|
1
bddisasm_test/x86/usermsr/rex2_valid_64.test
Normal file
1
bddisasm_test/x86/usermsr/rex2_valid_64.test
Normal file
@ -0,0 +1 @@
|
|||||||
|
Δηzψΐ"3DΔη{ψΐ"3Dσ8ψΑς8ψΑ
|
@ -1,6 +1,6 @@
|
|||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
SRC_FILES := bdshemu.c
|
SRC_FILES := bdshemu.c bdshemu_x86.c
|
||||||
|
|
||||||
OBJECTS := $(SRC_FILES:.c=.o)
|
OBJECTS := $(SRC_FILES:.c=.o)
|
||||||
|
|
||||||
@ -121,3 +121,4 @@ install: all
|
|||||||
install -m 644 $(OUT_DIR)/$(LIB_NAME) $(DESTDIR)$(PREFIX)/lib/
|
install -m 644 $(OUT_DIR)/$(LIB_NAME) $(DESTDIR)$(PREFIX)/lib/
|
||||||
install -d $(DESTDIR)$(PREFIX)/include/bddisasm/
|
install -d $(DESTDIR)$(PREFIX)/include/bddisasm/
|
||||||
cp -r ../inc/bdshemu.h $(DESTDIR)$(PREFIX)/include/bddisasm/
|
cp -r ../inc/bdshemu.h $(DESTDIR)$(PREFIX)/include/bddisasm/
|
||||||
|
cp -r ../inc/bdshemu_x86.h $(DESTDIR)$(PREFIX)/include/bddisasm/
|
3204
bdshemu/bdshemu.c
3204
bdshemu/bdshemu.c
File diff suppressed because it is too large
Load Diff
@ -643,10 +643,13 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="bdshemu.c" />
|
<ClCompile Include="bdshemu.c" />
|
||||||
|
<ClCompile Include="bdshemu_x86.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\inc\bddisasm_version.h" />
|
||||||
<ClInclude Include="..\inc\bdshemu.h" />
|
<ClInclude Include="..\inc\bdshemu.h" />
|
||||||
<ClInclude Include="..\inc\version.h" />
|
<ClInclude Include="..\inc\bdshemu_x86.h" />
|
||||||
|
<ClInclude Include="include\bdshemu_common.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -16,18 +16,36 @@
|
|||||||
<Filter Include="Header Files\public">
|
<Filter Include="Header Files\public">
|
||||||
<UniqueIdentifier>{e9031566-ae16-49a2-807a-b33729f7b1d4}</UniqueIdentifier>
|
<UniqueIdentifier>{e9031566-ae16-49a2-807a-b33729f7b1d4}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
<Filter Include="Header Files\public\x86">
|
||||||
<ItemGroup>
|
<UniqueIdentifier>{d95202e3-5db7-4437-aaee-b42dd317eb1b}</UniqueIdentifier>
|
||||||
<ClCompile Include="bdshemu.c">
|
</Filter>
|
||||||
<Filter>Source Files</Filter>
|
<Filter Include="Source Files\x86">
|
||||||
</ClCompile>
|
<UniqueIdentifier>{b37ad850-b053-4c49-a61c-81abc50c144e}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\private">
|
||||||
|
<UniqueIdentifier>{ca0d8798-3c56-489f-8cc5-fe315397c76a}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\inc\bdshemu.h">
|
<ClInclude Include="..\inc\bdshemu.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\inc\version.h">
|
<ClInclude Include="..\inc\bdshemu_x86.h">
|
||||||
|
<Filter>Header Files\public\x86</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\bdshemu_common.h">
|
||||||
|
<Filter>Header Files\private</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\bddisasm_version.h">
|
||||||
<Filter>Header Files\public</Filter>
|
<Filter>Header Files\public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="bdshemu.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="bdshemu_x86.c">
|
||||||
|
<Filter>Source Files\x86</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
3568
bdshemu/bdshemu_x86.c
Normal file
3568
bdshemu/bdshemu_x86.c
Normal file
File diff suppressed because it is too large
Load Diff
172
bdshemu/include/bdshemu_common.h
Normal file
172
bdshemu/include/bdshemu_common.h
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Bitdefender
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef BDSHEMU_COMMON_H_
|
||||||
|
#define BDSHEMU_COMMON_H_
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <sal.h>
|
||||||
|
#else
|
||||||
|
#define _Analysis_assume_(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// The SHELLBMP and STACKBMP are two bitmaps which hold the state of each shellcode byte and each stack byte.
|
||||||
|
// Inside SHELLBMP, we store whether a shellcode byte has been fetched for execution or not, and whether it was
|
||||||
|
// modified or not.
|
||||||
|
// Inside STACKBMP, we store whether a stack byte is part of a previously saved RIP value or not.
|
||||||
|
#define STACKBMP(ctx) ((ctx)->Intbuf)
|
||||||
|
#define STACKBMP_SIZE(ctx) ((ctx)->StackSize)
|
||||||
|
#define SHELLBMP(ctx) (!((ctx)->Options & SHEMU_OPT_DIRECT_MAPPED_SHELL) ? (ctx)->Intbuf + (ctx)->StackSize : ND_NULL)
|
||||||
|
#define SHELLBMP_SIZE(ctx) (!((ctx)->Options & SHEMU_OPT_DIRECT_MAPPED_SHELL) ? (ctx)->ShellcodeSize : 0)
|
||||||
|
#define MAX(a, b) ((a) < (b) ? (b) : (a))
|
||||||
|
#define MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||||
|
|
||||||
|
|
||||||
|
// Flags used for the shellcode. These are set inside SHELLBMP. Each byte at index X inside SHELLBMP indicates the state
|
||||||
|
// of the shellcode byte at index X.
|
||||||
|
#define SHELL_BYTE_DIRTY (0x01) // The location inside the shellcode has been written.
|
||||||
|
#define SHELL_BYTE_FETCHED (0x02) // The location inside the shellcode has been fetched for execution.
|
||||||
|
#define SHELL_BYTE_IBYTES (0x04) // The location inside the shellcode represents executed instruction
|
||||||
|
// bytes. Does not include the first instruction byte, which is marked
|
||||||
|
// using the SHELL_BYTE_FETCHED flag.
|
||||||
|
|
||||||
|
// Flags used for the stack. These are set inside STACKBMP. Each byte at index X inside STACKBMP indicates the state
|
||||||
|
// of the stack byte at index X.
|
||||||
|
#define STACK_BYTE_RIP (0x01) // The location inside the stack contains a RIP portion.
|
||||||
|
|
||||||
|
// Flags used for the GPR tracking mechanism. Each byte X inside the GPR tracker array indicates the state of said GPR.
|
||||||
|
#define GPR_TRACK_READ (0x01) // The GPR has been read, by any instruction (including RMW).
|
||||||
|
#define GPR_TRACK_DIRTY (0x02) // The GPR has been modified.
|
||||||
|
|
||||||
|
|
||||||
|
#define GET_BITS(val, start, stop) (((val) >> (start)) & ((1ULL << ((stop) - (start) + 1)) - 1))
|
||||||
|
|
||||||
|
#define ShemuShellBmpStateSet(Context, Start, Count, Flags) \
|
||||||
|
ShemuBmpStateUpdate(SHELLBMP(Context), SHELLBMP_SIZE(Context), Start, Count, Flags, ND_FALSE)
|
||||||
|
|
||||||
|
#define ShemuShellBmpStateClear(Context, Start, Count, Flags) \
|
||||||
|
ShemuBmpStateUpdate(SHELLBMP(Context), SHELLBMP_SIZE(Context), Start, Count, Flags, ND_TRUE)
|
||||||
|
|
||||||
|
#define ShemuShellBmpStateCheck(Context, Start, Count, Flags) \
|
||||||
|
ShemuBmpStateCheck(SHELLBMP(Context), SHELLBMP_SIZE(Context), Start, Count, Flags)
|
||||||
|
|
||||||
|
#define ShemuStackBmpStateSet(Contxt, Start, Count, Flags) \
|
||||||
|
ShemuBmpStateUpdate(STACKBMP(Context), STACKBMP_SIZE(Context), Start, Count, Flags, ND_FALSE)
|
||||||
|
|
||||||
|
#define ShemuStackBmpStateClear(Context, Start, Count, Flags) \
|
||||||
|
ShemuBmpStateUpdate(STACKBMP(Context), STACKBMP_SIZE(Context), Start, Count, Flags, ND_TRUE)
|
||||||
|
|
||||||
|
#define ShemuStackBmpStateCheck(Context, Start, Count, Flags) \
|
||||||
|
ShemuBmpStateCheck(STACKBMP(Context), STACKBMP_SIZE(Context), Start, Count, Flags)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
shemu_printf(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
char *formatstring,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
void *
|
||||||
|
shemu_memcpy(
|
||||||
|
void *Dest,
|
||||||
|
const void *Source,
|
||||||
|
ND_SIZET Size
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
ShemuHexlify(
|
||||||
|
ND_UINT8 *Value,
|
||||||
|
ND_UINT64 ValueSize,
|
||||||
|
char *Hex,
|
||||||
|
ND_UINT64 HexSize
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
ShemuBmpStateUpdate(
|
||||||
|
ND_UINT8 *Bitmap,
|
||||||
|
ND_UINT64 Size,
|
||||||
|
ND_UINT64 Start,
|
||||||
|
ND_UINT64 Count,
|
||||||
|
ND_UINT8 Flags,
|
||||||
|
ND_BOOL Clear
|
||||||
|
);
|
||||||
|
|
||||||
|
ND_BOOL
|
||||||
|
ShemuBmpStateCheck(
|
||||||
|
ND_UINT8 *Bitmap,
|
||||||
|
ND_UINT64 Size,
|
||||||
|
ND_UINT64 Start,
|
||||||
|
ND_UINT64 Count,
|
||||||
|
ND_UINT8 Flags
|
||||||
|
);
|
||||||
|
|
||||||
|
ND_BOOL
|
||||||
|
ShemuIsShellcodePtr(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size
|
||||||
|
);
|
||||||
|
|
||||||
|
ND_BOOL
|
||||||
|
ShemuIsStackPtr(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size
|
||||||
|
);
|
||||||
|
|
||||||
|
ND_BOOL
|
||||||
|
ShemuIsIcachePtr(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size
|
||||||
|
);
|
||||||
|
|
||||||
|
SHEMU_STATUS
|
||||||
|
ShemuMemLoad(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size,
|
||||||
|
ND_UINT8 *Value
|
||||||
|
);
|
||||||
|
|
||||||
|
SHEMU_STATUS
|
||||||
|
ShemuMemStore(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size,
|
||||||
|
ND_UINT8 *Value
|
||||||
|
);
|
||||||
|
|
||||||
|
SHEMU_STATUS
|
||||||
|
ShemuMemFetch(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size,
|
||||||
|
ND_UINT8 *Bytes
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
ShemuFlushIcache(
|
||||||
|
SHEMU_CONTEXT *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
ShemuDisplayMemValue(
|
||||||
|
SHEMU_CONTEXT *Context,
|
||||||
|
ND_UINT64 Gla,
|
||||||
|
ND_UINT64 Size,
|
||||||
|
ND_UINT8 *Value,
|
||||||
|
ND_BOOL Load
|
||||||
|
);
|
||||||
|
|
||||||
|
ND_BOOL
|
||||||
|
ShemuIsImmMetasploitHash(
|
||||||
|
ND_UINT64 Value
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif // BDSHEMU_COMMON_H_
|
@ -1,6 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
option(BDD_FUZZ_WITH_LOGS "Enable logging for the fuzzer" OFF)
|
option(BDD_FUZZ_WITH_LOGS "Enable logging for the fuzzer" OFF)
|
||||||
|
option(BDD_FUZZ_DIRECT_MAP "Enable direct SHEMU_OPT_DIRECT_MAPPED_SHELL" OFF)
|
||||||
|
|
||||||
project(bdshemu_fuzzer LANGUAGES C)
|
project(bdshemu_fuzzer LANGUAGES C)
|
||||||
|
|
||||||
@ -17,4 +18,23 @@ if (BDD_FUZZ_WITH_LOGS)
|
|||||||
target_compile_definitions(shfuzzx64 PRIVATE ENABLE_LOGGING)
|
target_compile_definitions(shfuzzx64 PRIVATE ENABLE_LOGGING)
|
||||||
endif (BDD_FUZZ_WITH_LOGS)
|
endif (BDD_FUZZ_WITH_LOGS)
|
||||||
|
|
||||||
|
if (BDD_FUZZ_DIRECT_MAP)
|
||||||
|
target_compile_definitions(shfuzzx86 PRIVATE DIRECT_MAP)
|
||||||
|
target_compile_definitions(shfuzzx64 PRIVATE DIRECT_MAP)
|
||||||
|
endif (BDD_FUZZ_DIRECT_MAP)
|
||||||
|
|
||||||
|
# Using CMAKE_C_COMPILER_ID to check for this will not work because afl-gcc is reported as gcc, while afl-clang and
|
||||||
|
# afl-clang-fast are reported as clang.
|
||||||
|
# We also don't want to use libfuzzer with AFL because it seems to have some build issues.
|
||||||
|
# TODO: but it should work, see https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/AFL_integration.md#how
|
||||||
|
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" AND NOT "${CMAKE_C_COMPILER}" MATCHES "afl-.*")
|
||||||
|
message(STATUS "Will use libfuzzer")
|
||||||
|
|
||||||
|
target_compile_options(shfuzzx86 PRIVATE -fsanitize=fuzzer)
|
||||||
|
target_link_libraries(shfuzzx86 PRIVATE -fsanitize=fuzzer)
|
||||||
|
|
||||||
|
target_compile_options(shfuzzx64 PRIVATE -fsanitize=fuzzer)
|
||||||
|
target_link_libraries(shfuzzx64 PRIVATE -fsanitize=fuzzer)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_custom_target(shfuzz DEPENDS shfuzzx86 shfuzzx64)
|
add_custom_target(shfuzz DEPENDS shfuzzx86 shfuzzx64)
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
# Bitdefender Shellocde Emulator Fuzzer
|
|
||||||
|
|
||||||
This assumes that you have [AFL](https://github.com/google/AFL) in your path.
|
|
||||||
|
|
||||||
It collects the `bddisasm` and `bdshemu` sources into a single executable, built with AFL instrumentation.
|
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
Build it with `make shfuzz`.
|
|
||||||
|
|
||||||
Start fuzzing with `make fuzz32` (for 32-bit mode samples) or `make fuzz64` (for 64-bit mode samples).
|
|
||||||
|
|
||||||
If you're in a hurry you can fuzz in the quick and dirty mode with `DIRTY=y`: `make fuzz32 DIRTY=y` or `make fuzz64 DIRTY=y`.
|
|
||||||
|
|
||||||
Activate support for [address sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) with `AFL_USE_ASAN=1 make shfuzz`. This can uncover more bugs, but it is a lot slower and requires more memory.
|
|
||||||
|
|
||||||
Input files are in the `in-32` and `in-64` directories, crashes will be in `out-32/crashes` or `out-64/crashes`, hangs will be in `out-32/hangs` or `out-64/hangs`.
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
If the `AFL_COMPILER` variable is not set, the build process looks for `afl-clang-fast` and if it is available, the tool is compiled with that. If not, it tries to choose between `afl-clang` and `afl-gcc`.
|
|
||||||
If you want to use a certain compiler simply set `AFL_COMPILER` before invoking make: `AFL_COMPILER=afl-gcc make`.
|
|
||||||
Note that `afl-clang-fast` is not compiled by default when compiling AFL. See [llvm mode](https://github.com/google/AFL/tree/master/llvm_mode) in the AFL repository.
|
|
||||||
|
|
||||||
Run the fuzzer in 32-bit mode with `make fuzz32`, or in 64-bit mode with `make fuzz64`.
|
|
||||||
|
|
||||||
If you want to take advantage of multiple cores see [parallel fuzzing](https://github.com/google/AFL/blob/master/docs/parallel_fuzzing.txt).
|
|
||||||
|
|
||||||
If `afl-clang-fast` is used, we try to use AFL in persistent mode, which should provide better performance.
|
|
||||||
|
|
||||||
Note that both `fuzz32` and `fuzz64` assume that the tool was compiled with `afl-clang-fast`, `afl-clang`, or `afl-gcc`.
|
|
||||||
|
|
||||||
ASAN builds will have increased memory requirements. You may need to tweak the `-m` parameter (or set `AFL_MEMORY`) for `afl-fuzz` (see [notes for ASAN](https://github.com/google/AFL/blob/master/docs/notes_for_asan.txt)).
|
|
||||||
|
|
||||||
By default, all logging is disabled, as it is already not visible while AFL is running. Compile with `LOG=y` in order to enable some minimal logging.
|
|
||||||
|
|
||||||
## Using the tool
|
|
||||||
|
|
||||||
The `shfuzz` tool is a simplified version of `disasmtool`. It takes 3 positional arguments:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
shfuzz file mode use_logging
|
|
||||||
```
|
|
||||||
|
|
||||||
- file - the path to a input file that contains instructions to be disassembled and emulated;
|
|
||||||
- mode - the mode in which to run: `32` for 32-bit instructions, `64` for 64-bit instruction;
|
|
||||||
- use_logging - if present, will actually log everything that `bdshemu` wants to log; even if absent, the `ShemuLog` implementation will still try to access every character in the string it should normally print, so if you want to find bugs related to logging you can still do, but it is a lot faster when the strings don't get printed. This is ignored if you compile `shfuzz` without `LOG=y`.
|
|
||||||
|
|
||||||
Any errors encountered while parsing the arguments, trying to open the input file, or allocate memory are handled by calling `abort()`. This makes it easier to detect these problems.
|
|
@ -25,11 +25,37 @@
|
|||||||
#define LOG(fmt, ...)
|
#define LOG(fmt, ...)
|
||||||
#endif // ENABLE_LOGGING
|
#endif // ENABLE_LOGGING
|
||||||
|
|
||||||
void ShemuLog(char *data)
|
#define DEFAULT_OPTIONS (SHEMU_OPT_TRACE_EMULATION |\
|
||||||
|
SHEMU_OPT_SUPPORT_AES |\
|
||||||
|
SHEMU_OPT_SUPPORT_APX)
|
||||||
|
|
||||||
|
void ShemuLog(char *data, void *ctx)
|
||||||
{
|
{
|
||||||
|
(void)(ctx);
|
||||||
LOG("%s", data);
|
LOG("%s", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ND_BOOL
|
||||||
|
access_shellcode(void *Ctx, ND_UINT64 Gla, ND_SIZET Size, ND_UINT8 *Buffer, ND_BOOL Store)
|
||||||
|
{
|
||||||
|
SHEMU_CONTEXT *ctx = Ctx;
|
||||||
|
ND_UINT32 offset;
|
||||||
|
|
||||||
|
offset = (ND_UINT32)(Gla - ctx->ShellcodeBase);
|
||||||
|
|
||||||
|
if (Store)
|
||||||
|
{
|
||||||
|
memcpy(ctx->Shellcode + offset, Buffer, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(Buffer, ctx->Shellcode + offset, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(FUZZ_X86) || defined(FUZZ_X64)
|
||||||
#ifdef FUZZ_X86
|
#ifdef FUZZ_X86
|
||||||
#define DEF_CODE ND_CODE_32
|
#define DEF_CODE ND_CODE_32
|
||||||
#define FUZZER_TYPE "x86"
|
#define FUZZER_TYPE "x86"
|
||||||
@ -45,6 +71,13 @@ void run_shemu(uint8_t *Data, size_t Size)
|
|||||||
SHEMU_CONTEXT ctx = { 0 };
|
SHEMU_CONTEXT ctx = { 0 };
|
||||||
SHEMU_STATUS shs;
|
SHEMU_STATUS shs;
|
||||||
|
|
||||||
|
#if defined(DIRECT_MAP)
|
||||||
|
ctx.AccessShellcode = access_shellcode;
|
||||||
|
ctx.Options |= SHEMU_OPT_DIRECT_MAPPED_SHELL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctx.ArchType = SHEMU_ARCH_TYPE_X86;
|
||||||
|
|
||||||
ctx.Shellcode = Data;
|
ctx.Shellcode = Data;
|
||||||
|
|
||||||
ctx.Stack = calloc(1, 0x2000);
|
ctx.Stack = calloc(1, 0x2000);
|
||||||
@ -65,28 +98,28 @@ void run_shemu(uint8_t *Data, size_t Size)
|
|||||||
ctx.ShellcodeSize = (uint32_t)Size;
|
ctx.ShellcodeSize = (uint32_t)Size;
|
||||||
ctx.StackBase = 0x100000;
|
ctx.StackBase = 0x100000;
|
||||||
ctx.StackSize = 0x2000;
|
ctx.StackSize = 0x2000;
|
||||||
ctx.Registers.RegRsp = 0x101000;
|
ctx.Arch.X86.Registers.RegRsp = 0x101000;
|
||||||
ctx.IntbufSize = (uint32_t)Size + 0x2000;
|
ctx.IntbufSize = (uint32_t)Size + 0x2000;
|
||||||
|
|
||||||
ctx.Registers.RegFlags = NDR_RFLAG_IF | 2;
|
ctx.Arch.X86.Registers.RegFlags = NDR_RFLAG_IF | 2;
|
||||||
ctx.Registers.RegRip = ctx.ShellcodeBase;
|
ctx.Arch.X86.Registers.RegRip = ctx.ShellcodeBase;
|
||||||
|
|
||||||
ctx.Segments.Cs.Selector = 0x10;
|
ctx.Arch.X86.Segments.Cs.Selector = 0x10;
|
||||||
ctx.Segments.Ds.Selector = 0x28;
|
ctx.Arch.X86.Segments.Ds.Selector = 0x28;
|
||||||
ctx.Segments.Es.Selector = 0x28;
|
ctx.Arch.X86.Segments.Es.Selector = 0x28;
|
||||||
ctx.Segments.Ss.Selector = 0x28;
|
ctx.Arch.X86.Segments.Ss.Selector = 0x28;
|
||||||
ctx.Segments.Fs.Selector = 0x30;
|
ctx.Arch.X86.Segments.Fs.Selector = 0x30;
|
||||||
ctx.Segments.Fs.Base = 0x7FFF0000;
|
ctx.Arch.X86.Segments.Fs.Base = 0x7FFF0000;
|
||||||
ctx.Segments.Gs.Selector = 0x30;
|
ctx.Arch.X86.Segments.Gs.Selector = 0x30;
|
||||||
ctx.Segments.Gs.Base = 0x7FFF0000;
|
ctx.Arch.X86.Segments.Gs.Base = 0x7FFF0000;
|
||||||
|
|
||||||
ctx.Mode = DEF_CODE;
|
ctx.Arch.X86.Mode = DEF_CODE;
|
||||||
ctx.Ring = 3;
|
ctx.Arch.X86.Ring = 3;
|
||||||
ctx.TibBase = ctx.Mode == ND_CODE_32 ? ctx.Segments.Fs.Base : ctx.Segments.Gs.Base;
|
ctx.TibBase = ctx.Arch.X86.Mode == ND_CODE_32 ? ctx.Arch.X86.Segments.Fs.Base : ctx.Arch.X86.Segments.Gs.Base;
|
||||||
ctx.MaxInstructionsCount = 4096;
|
ctx.MaxInstructionsCount = 4096;
|
||||||
ctx.Log = &ShemuLog;
|
ctx.Log = &ShemuLog;
|
||||||
ctx.Flags = 0;
|
ctx.Flags = 0;
|
||||||
ctx.Options = SHEMU_OPT_TRACE_EMULATION;
|
ctx.Options |= DEFAULT_OPTIONS;
|
||||||
|
|
||||||
shs = ShemuEmulate(&ctx);
|
shs = ShemuEmulate(&ctx);
|
||||||
LOG("[+] Shemu returned: 0x%08x\n", shs);
|
LOG("[+] Shemu returned: 0x%08x\n", shs);
|
||||||
@ -94,10 +127,11 @@ void run_shemu(uint8_t *Data, size_t Size)
|
|||||||
free(ctx.Intbuf);
|
free(ctx.Intbuf);
|
||||||
free(ctx.Stack);
|
free(ctx.Stack);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#error "Do not know what to fuzz, define one of FUZZ_X86, FUZZ_X64"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__AFL_FUZZ_TESTCASE_LEN)
|
#if defined(__AFL_FUZZ_TESTCASE_LEN)
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
// See https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md
|
// See https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md
|
||||||
__AFL_FUZZ_INIT();
|
__AFL_FUZZ_INIT();
|
||||||
|
|
||||||
|
21
bdshemu_fuzz/fuzzing_image_entrypoint.sh
Normal file
21
bdshemu_fuzz/fuzzing_image_entrypoint.sh
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check if the -it flag is provided
|
||||||
|
if [ -t 0 ] && [ -t 1 ]; then
|
||||||
|
echo "Running in interactive mode"
|
||||||
|
else
|
||||||
|
echo "Error: This container requires an interactive shell (-it flag)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the volume directory is present
|
||||||
|
if [ ! -d "${SHARE_DIR}" ]; then
|
||||||
|
echo "Warning: Volume directory '${SHARE_DIR}' is missing."
|
||||||
|
echo "Please use the -v flag to specify a host directory."
|
||||||
|
echo "For example 'podman run -v /host/path:${SHARE_DIR}'"
|
||||||
|
echo "You will need to manually copy fuzzing inputs/outputs from/to the host"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Continue with the original command
|
||||||
|
exec "$@"
|
@ -1,7 +1,7 @@
|
|||||||
# Shellcode Emulator Tests
|
# Shellcode Emulator Tests
|
||||||
|
|
||||||
These tests are used to validate basic bdshemu functionality. Each test consists of up to three files:
|
These tests are used to validate basic bdshemu functionality. Each test consists of up to three files:
|
||||||
* The binary test file. The name format for this type of file is `name_32|64[_r0]`. No extension must be provided; 32 indicates 32 bit test file, 64 indicates 64 bit test file, and r0 indicates kernel payload
|
* The binary test file. The name format for this type of file is `name_32|64[_r0].test`. 32 indicates 32 bit test file, 64 indicates 64 bit test file, and r0 indicates kernel payload
|
||||||
* The output result file. Must be named the same as the binary test file, but with the extension .result
|
* The output result file. Must be named the same as the binary test file, but with the extension .result
|
||||||
* Optional assembly file, used to generate the binary test file
|
* Optional assembly file, used to generate the binary test file
|
||||||
|
|
||||||
|
Binary file not shown.
@ -5,38 +5,61 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import glob
|
import glob
|
||||||
|
import shutil
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
total_tests = 0
|
TEMP_PATH = "!temp"
|
||||||
failed_tests = 0
|
|
||||||
|
|
||||||
def test_dir(dir):
|
# A test file-name contains some indicators as to how the emulation should be done:
|
||||||
global total_tests
|
# - If '_16' is present in the name, emulation will be done on 16 bit
|
||||||
global failed_tests
|
# - If '_32' is present in the name, emulation will be done on 32 bit
|
||||||
|
# - If '_64' is present in the name, emulation will be done on 64 bit
|
||||||
|
# - If '_r0' is present in the name, emulation will be done as kernel code
|
||||||
|
# A test case consists of minimum two files:
|
||||||
|
# - An '.test' file, containing the binary code to be emulated
|
||||||
|
# - An '.result' file, containing the emulation output
|
||||||
|
# A test is considered passed if the output produced during emulation is identical to the
|
||||||
|
# output containted in the '.result' file.
|
||||||
|
|
||||||
for f in glob.glob('%s\\*' % dir):
|
#
|
||||||
if -1 == f.find('.'):
|
# test_dir
|
||||||
if 0 < f.find('_16'):
|
#
|
||||||
|
# Runs the tests inside the provided directory.
|
||||||
|
# Returns a tuplecontaining the total number of tests run and the number of failed tests.
|
||||||
|
#
|
||||||
|
def test_dir(dir, arch='x86'):
|
||||||
|
total_tests = 0
|
||||||
|
failed_tests = 0
|
||||||
|
|
||||||
|
for f in glob.glob('%s\\*.test' % dir):
|
||||||
|
base, _ = os.path.splitext(f)
|
||||||
|
|
||||||
|
tst_file = f
|
||||||
|
res_file = base + '.result'
|
||||||
|
tmp_file = base + '.temp'
|
||||||
|
|
||||||
|
if 0 < tst_file.find('_16'):
|
||||||
mod = '-b16'
|
mod = '-b16'
|
||||||
elif 0 < f.find('_32'):
|
elif 0 < tst_file.find('_32'):
|
||||||
mod = '-b32'
|
mod = '-b32'
|
||||||
else:
|
else:
|
||||||
mod = '-b64'
|
mod = '-b64'
|
||||||
if 0 < f.find('_r0'):
|
|
||||||
|
if 0 < tst_file.find('_r0'):
|
||||||
mod += ' -k'
|
mod += ' -k'
|
||||||
|
|
||||||
print(' * Running test case %s...' % f)
|
print(' * Running test case %s...' % tst_file)
|
||||||
os.system('disasm shemu %s -f %s >%s.temp' % (mod, f, f))
|
os.system('disasm shemu %s -f %s >%s' % (mod, tst_file, tmp_file))
|
||||||
try:
|
try:
|
||||||
res = open('%s.result' % f).read()
|
res = open(res_file).read()
|
||||||
except:
|
except:
|
||||||
print(' ! No result file provided for test %s!' % f)
|
print(' ! No result file provided for test %s!' % tst_file)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tmp = open('%s.temp' % f).read()
|
tmp = open(tmp_file).read()
|
||||||
except:
|
except:
|
||||||
print(' ! No result produced by test %s!' % f)
|
print(' ! No result produced by test %s!' % tst_file)
|
||||||
|
|
||||||
total_tests += 1
|
total_tests += 1
|
||||||
if res != tmp:
|
if res != tmp:
|
||||||
@ -45,47 +68,112 @@ def test_dir(dir):
|
|||||||
else:
|
else:
|
||||||
print(' * Passed.')
|
print(' * Passed.')
|
||||||
|
|
||||||
for f in glob.glob('%s\\*_decoded.bin' % dir):
|
# Cleanup.
|
||||||
os.remove(f)
|
os.remove(tmp_file)
|
||||||
for f in glob.glob('%s\\*.temp' % dir):
|
os.remove(tst_file + "_decoded.bin")
|
||||||
os.remove(f)
|
|
||||||
|
return (total_tests, failed_tests)
|
||||||
|
|
||||||
|
#
|
||||||
|
# regenerate
|
||||||
|
#
|
||||||
|
def regenerate(dir, arch='x86'):
|
||||||
|
for f in glob.glob('%s\\*.test' % dir):
|
||||||
|
base, _ = os.path.splitext(f)
|
||||||
|
|
||||||
|
tst_file = f
|
||||||
|
res_file = base + '.result'
|
||||||
|
|
||||||
def regenerate(dir):
|
|
||||||
for f in glob.glob('%s\\*' % dir):
|
|
||||||
if -1 == f.find('.'):
|
|
||||||
if 0 < f.find('_16'):
|
if 0 < f.find('_16'):
|
||||||
mod = '-b16'
|
mod = '-b16'
|
||||||
elif 0 < f.find('_32'):
|
elif 0 < f.find('_32'):
|
||||||
mod = '-b32'
|
mod = '-b32'
|
||||||
else:
|
else:
|
||||||
mod = '-b64'
|
mod = '-b64'
|
||||||
|
|
||||||
if 0 < f.find('_r0'):
|
if 0 < f.find('_r0'):
|
||||||
mod += ' -k'
|
mod += ' -k'
|
||||||
|
|
||||||
print(' * Regenerating test case %s...' % f)
|
print(' * Regenerating test case %s...' % tst_file)
|
||||||
os.system('disasm -exi shemu %s -f %s >%s.result' % (mod, f, f))
|
os.system('disasm -exi shemu %s -f %s >%s' % (mod, tst_file, res_file))
|
||||||
|
|
||||||
for f in glob.glob('%s\\*_decoded.bin' % dir):
|
# Cleanup.
|
||||||
os.remove(f)
|
os.remove(tst_file + "_decoded.bin")
|
||||||
|
|
||||||
cleanup_files = []
|
#
|
||||||
|
# parse_dir_rec
|
||||||
|
#
|
||||||
|
def parse_dir_rec(dir, arch, handler):
|
||||||
|
for f in glob.glob(dir + "\\*"):
|
||||||
|
path, name = os.path.split(f)
|
||||||
|
if name in ['.', '..']:
|
||||||
|
continue
|
||||||
|
if os.path.isdir(f):
|
||||||
|
parse_dir_rec(f, arch, handler)
|
||||||
|
handler(f, arch)
|
||||||
|
|
||||||
print("Extracting test archive...\n")
|
|
||||||
with ZipFile('bdshemu_test.zip') as zf:
|
#
|
||||||
|
# test_archive
|
||||||
|
#
|
||||||
|
def test_archive(filename, arch='x86'):
|
||||||
|
cleanup_files = []
|
||||||
|
|
||||||
|
# Run the x86 test.
|
||||||
|
print("Extracting test archive...")
|
||||||
|
with ZipFile(filename) as zf:
|
||||||
cleanup_files = zf.namelist()
|
cleanup_files = zf.namelist()
|
||||||
zf.extractall()
|
zf.extractall(path=TEMP_PATH)
|
||||||
print("Done!\n")
|
zf.close()
|
||||||
|
|
||||||
for dn in glob.glob("*"):
|
print("Running tests...")
|
||||||
|
total_tests, failed_tests = 0, 0
|
||||||
|
for dn in glob.glob(os.path.join(TEMP_PATH, "*")):
|
||||||
if not os.path.isdir(dn):
|
if not os.path.isdir(dn):
|
||||||
continue
|
continue
|
||||||
print('Testing %s...' % dn)
|
print('Testing %s...' % dn)
|
||||||
test_dir(dn)
|
cnt_tests, cnt_failed = test_dir(dn, arch)
|
||||||
print("Ran %d tests, %d failed" % (total_tests, failed_tests))
|
|
||||||
|
|
||||||
print("Cleaning up test files...\n")
|
total_tests += cnt_tests
|
||||||
for f in cleanup_files:
|
failed_tests += cnt_failed
|
||||||
p = Path(os.getcwd()) / f
|
|
||||||
if p.is_file():
|
print("========================================================================")
|
||||||
p.unlink()
|
print("Summary:")
|
||||||
print("Done!\n")
|
print("Ran %d tests, %d failed" % (total_tests, failed_tests))
|
||||||
|
print("========================================================================")
|
||||||
|
print()
|
||||||
|
|
||||||
|
shutil.rmtree(TEMP_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# No arguments provided, auto-run all tests.
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
print("Running x86 tests...")
|
||||||
|
test_archive("x86\\bdshemu_test_x86.zip")
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
opt_dir = ""
|
||||||
|
opt_regen = False
|
||||||
|
opt_arch = 'x86'
|
||||||
|
|
||||||
|
for arg in sys.argv[1:]:
|
||||||
|
if os.path.isdir(arg):
|
||||||
|
print("Will test directory", arg)
|
||||||
|
opt_dir = arg
|
||||||
|
if arg == "regenerate":
|
||||||
|
print("Will regenerate tests...")
|
||||||
|
opt_regen = True
|
||||||
|
|
||||||
|
print("Identified architecture: ", opt_arch)
|
||||||
|
|
||||||
|
# Single directory test.
|
||||||
|
if not opt_dir:
|
||||||
|
print("A directory containing tests must be supplied!")
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
if opt_regen:
|
||||||
|
parse_dir_rec(opt_dir, opt_arch, regenerate)
|
||||||
|
else:
|
||||||
|
parse_dir_rec(opt_dir, opt_arch, test_dir)
|
BIN
bdshemu_test/x86/bdshemu_test_x86.zip
Normal file
BIN
bdshemu_test/x86/bdshemu_test_x86.zip
Normal file
Binary file not shown.
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||||
|
|
||||||
#if _MSC_VER
|
#ifdef _MSC_VER
|
||||||
int nd_vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list argptr)
|
int nd_vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list argptr)
|
||||||
{
|
{
|
||||||
return vsnprintf(buffer, size, format, argptr);
|
return vsnprintf(buffer, size, format, argptr);
|
||||||
|
@ -165,13 +165,10 @@
|
|||||||
%define __x86_64__
|
%define __x86_64__
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
|
||||||
%include "bddisasm.h"
|
%include "bddisasm.h"
|
||||||
%include "constants.h"
|
%include "bdx86_constants.h"
|
||||||
%include "cpuidflags.h"
|
%include "bdx86_cpuidflags.h"
|
||||||
%include "disasmstatus.h"
|
%include "bddisasm_status.h"
|
||||||
%include "disasmtypes.h"
|
%include "bddisasm_types.h"
|
||||||
%include "registers.h"
|
%include "bdx86_registers.h"
|
||||||
%include "version.h"
|
%include "bdx86_core.h"
|
||||||
|
|
||||||
%include "pybddisasm.h"
|
|
||||||
|
@ -12,7 +12,7 @@ from setuptools import find_packages, setup, Command, Extension, Distribution
|
|||||||
from codecs import open
|
from codecs import open
|
||||||
|
|
||||||
VERSION = (0, 3, 0)
|
VERSION = (0, 3, 0)
|
||||||
LIBRARY_VERSION = (1, 38, 0)
|
LIBRARY_VERSION = (2, 1, 0)
|
||||||
DIR_INCLUDE = '../../inc'
|
DIR_INCLUDE = '../../inc'
|
||||||
|
|
||||||
here = os.path.abspath(os.path.dirname(__file__))
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
@ -25,7 +25,6 @@ __library_dirs = ['../../build', '../../bin/x64/Release']
|
|||||||
__packages = ['pybddisasm']
|
__packages = ['pybddisasm']
|
||||||
__requires = ['setuptools']
|
__requires = ['setuptools']
|
||||||
|
|
||||||
|
|
||||||
class BinaryDistribution(Distribution):
|
class BinaryDistribution(Distribution):
|
||||||
def has_ext_modules(arg):
|
def has_ext_modules(arg):
|
||||||
return True
|
return True
|
||||||
@ -33,10 +32,8 @@ class BinaryDistribution(Distribution):
|
|||||||
def is_pure(self):
|
def is_pure(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __fn_validate_compatibility():
|
def __fn_validate_compatibility():
|
||||||
print(os.getcwd())
|
version_header = '%s/bddisasm_version.h' % (DIR_INCLUDE)
|
||||||
version_header = '%s/version.h' % (DIR_INCLUDE)
|
|
||||||
with open(version_header, 'r') as file:
|
with open(version_header, 'r') as file:
|
||||||
data = file.read()
|
data = file.read()
|
||||||
|
|
||||||
@ -65,7 +62,6 @@ def __fn_validate_compatibility():
|
|||||||
LIBRARY_VERSION[1], LIBRARY_VERSION[2]))
|
LIBRARY_VERSION[1], LIBRARY_VERSION[2]))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
__fn_validate_compatibility()
|
__fn_validate_compatibility()
|
||||||
|
|
||||||
with open('README.md', 'r', 'utf-8') as f:
|
with open('README.md', 'r', 'utf-8') as f:
|
||||||
@ -91,11 +87,12 @@ setup(
|
|||||||
install_requires=__requires,
|
install_requires=__requires,
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
'Programming Language :: Python :: 3.5',
|
||||||
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
'Programming Language :: Python :: 3.9',
|
'Programming Language :: Python :: 3.9',
|
||||||
'Programming Language :: Python :: 3.10',
|
'Programming Language :: Python :: 3.10',
|
||||||
'Programming Language :: Python :: 3.11',
|
|
||||||
'License :: OSI Approved :: Apache Software License',
|
'License :: OSI Approved :: Apache Software License',
|
||||||
'Operating System :: Microsoft :: Windows',
|
'Operating System :: Microsoft :: Windows',
|
||||||
'Operating System :: POSIX :: Linux'
|
'Operating System :: POSIX :: Linux'
|
||||||
|
@ -4,3 +4,6 @@ members = [
|
|||||||
"bddisasm-sys",
|
"bddisasm-sys",
|
||||||
"bddisasm",
|
"bddisasm",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.2.3"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bddisasm-sys"
|
name = "bddisasm-sys"
|
||||||
version = "0.4.0"
|
version.workspace = true
|
||||||
authors = ["Cristi Anichitei <ianichitei@bitdefender.com>"]
|
authors = ["Cristi Anichitei <ianichitei@bitdefender.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
links = "bddisasm"
|
links = "bddisasm"
|
||||||
|
@ -9,10 +9,10 @@ fn main() {
|
|||||||
println!("cargo:rerun-if-changed=csrc");
|
println!("cargo:rerun-if-changed=csrc");
|
||||||
|
|
||||||
cc::Build::new()
|
cc::Build::new()
|
||||||
.file("csrc/bddisasm/bddisasm.c")
|
.file("csrc/bddisasm/bddisasm_crt.c")
|
||||||
.file("csrc/bddisasm/bdformat.c")
|
.file("csrc/bddisasm/bdx86_decoder.c")
|
||||||
.file("csrc/bddisasm/bdhelpers.c")
|
.file("csrc/bddisasm/bdx86_formatter.c")
|
||||||
.file("csrc/bddisasm/crt.c")
|
.file("csrc/bddisasm/bdx86_helpers.c")
|
||||||
.include("csrc/bddisasm/include")
|
.include("csrc/bddisasm/include")
|
||||||
.include("csrc/inc")
|
.include("csrc/inc")
|
||||||
.define("BDDISASM_HAS_VSNPRINTF", Some("1"))
|
.define("BDDISASM_HAS_VSNPRINTF", Some("1"))
|
||||||
|
@ -30,8 +30,8 @@ mod tests {
|
|||||||
let mut major: u32 = 0;
|
let mut major: u32 = 0;
|
||||||
let mut minor: u32 = 0;
|
let mut minor: u32 = 0;
|
||||||
let mut revision: u32 = 0;
|
let mut revision: u32 = 0;
|
||||||
let mut build_date: *mut c_char = std::ptr::null_mut();
|
let mut build_date: *const c_char = std::ptr::null();
|
||||||
let mut build_time: *mut c_char = std::ptr::null_mut();
|
let mut build_time: *const c_char = std::ptr::null();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
NdGetVersion(
|
NdGetVersion(
|
||||||
@ -53,7 +53,7 @@ mod tests {
|
|||||||
|
|
||||||
// There are no other asserts in this test. Enforcing a known minor version is not worth it, we mainly want to
|
// There are no other asserts in this test. Enforcing a known minor version is not worth it, we mainly want to
|
||||||
// see that `NdGetVersion` works.
|
// see that `NdGetVersion` works.
|
||||||
assert_eq!(major, 1);
|
assert_eq!(major, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_decode(code: &[u8]) -> (INSTRUX, NDSTATUS) {
|
fn do_decode(code: &[u8]) -> (INSTRUX, NDSTATUS) {
|
||||||
@ -79,10 +79,7 @@ mod tests {
|
|||||||
let (instrux, status) = do_decode(&code);
|
let (instrux, status) = do_decode(&code);
|
||||||
|
|
||||||
assert_eq!(status, 0, "Failed to decode instruction {:#x?}", code);
|
assert_eq!(status, 0, "Failed to decode instruction {:#x?}", code);
|
||||||
assert_eq!(
|
assert_eq!(instrux.Instruction, _ND_INS_CLASS::ND_INS_NOP);
|
||||||
unsafe { instrux.__bindgen_anon_2.Instruction },
|
|
||||||
_ND_INS_CLASS::ND_INS_NOP
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2,19 +2,13 @@
|
|||||||
|
|
||||||
## 0.3.1
|
## 0.3.1
|
||||||
|
|
||||||
### Added
|
### Removed
|
||||||
|
|
||||||
- support for new Intel ISA, per Intel Architecture Instruction Set Extensions and Future Features document #319433-049 (June 2023): AVX-NNI-INT16, SHA512, SM3, SM4, TSE.
|
- the `ExceptionClass` enum
|
||||||
|
- `sse_cond`, `has_mvex`, `has_drex`, `has_imm3`, `immediate3`, `sign_disp`, `imm3_length`, `imm3_offset`, `bhint` from `DecodedInstruction`
|
||||||
### Changed
|
- multiple variants from `Category`, `IsaSet`, `Mnemonic` in accordance with the changes in `bddisasm`
|
||||||
|
- `raw_size`, `decorator` from `Operand`
|
||||||
- `Mnemonic`, `IsaSet`, and `Category` use all caps for the enum variants
|
- the `Operand` struct
|
||||||
|
|
||||||
## 0.3.0
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- #84: handle 0 sizes in `OpSize::from_raw`
|
|
||||||
|
|
||||||
## 0.2.1
|
## 0.2.1
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bddisasm"
|
name = "bddisasm"
|
||||||
version = "0.3.0"
|
version.workspace = true
|
||||||
authors = ["Cristi Anichitei <ianichitei@bitdefender.com>"]
|
authors = ["Cristi Anichitei <ianichitei@bitdefender.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
@ -14,7 +14,7 @@ categories = ["api-bindings", "hardware-support"]
|
|||||||
keywords = ["disassembler", "decoder", "x86", "amd64", "x86_64"]
|
keywords = ["disassembler", "decoder", "x86", "amd64", "x86_64"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bddisasm-sys = { version = "0.4.0", path = "../bddisasm-sys" }
|
bddisasm-sys = { version = "0.2.3", path = "../bddisasm-sys" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = []
|
std = []
|
||||||
@ -23,5 +23,5 @@ std = []
|
|||||||
all-features = true
|
all-features = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0.0"
|
||||||
clap = "2.34.0"
|
clap = "2.34.0"
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
// TODO: maybe use something like the `bitflags` crate and have all these as flags?
|
// TODO: maybe use something like the `bitflags` crate and have all these as flags?
|
||||||
|
|
||||||
/// Privilege levels (rings) in which an instruction is supported.
|
/// Privilege levels (rings) in which an instruction is supported.
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct PrivilegeLevel {
|
pub struct PrivilegeLevel {
|
||||||
/// Instruction is valid in ring 0.
|
/// Instruction is valid in ring 0.
|
||||||
@ -45,6 +46,7 @@ pub struct PrivilegeLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Operating modes in which an instruction is supported.
|
/// Operating modes in which an instruction is supported.
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct OperatingMode {
|
pub struct OperatingMode {
|
||||||
/// The instruction is valid in real mode.
|
/// The instruction is valid in real mode.
|
||||||
@ -64,6 +66,7 @@ pub struct OperatingMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Special modes - these may be active inside other modes (example: `TSX` in `Long mode`).
|
/// Special modes - these may be active inside other modes (example: `TSX` in `Long mode`).
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct SpecialModes {
|
pub struct SpecialModes {
|
||||||
/// The instruction is valid in System Management Mode.
|
/// The instruction is valid in System Management Mode.
|
||||||
@ -86,6 +89,7 @@ pub struct SpecialModes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// VMX mode - they engulf all the other modes.
|
/// VMX mode - they engulf all the other modes.
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct VmxMode {
|
pub struct VmxMode {
|
||||||
/// The instruction is valid in VMX root mode.
|
/// The instruction is valid in VMX root mode.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//!
|
//!
|
||||||
//! # Notes
|
//! # Notes
|
||||||
//!
|
//!
|
||||||
//! All error codes that can be returned by `bddisasm-sys` are encapsulated in the [`DecodeError`](DecodeError) enum.
|
//! All error codes that can be returned by `bddisasm-sys` are encapsulated in the [`DecodeError`] enum.
|
||||||
//! However, some of these are unlikely to be encountered when using this crate (for example,
|
//! However, some of these are unlikely to be encountered when using this crate (for example,
|
||||||
//! [`BufferOverflow`](DecodeError::BufferOverflow)) which indicates that a buffer passed to the `bddisasm` C library is
|
//! [`BufferOverflow`](DecodeError::BufferOverflow)) which indicates that a buffer passed to the `bddisasm` C library is
|
||||||
//! not large enough.
|
//! not large enough.
|
||||||
@ -117,6 +117,9 @@ pub enum DecodeError {
|
|||||||
/// Not enough space is available.
|
/// Not enough space is available.
|
||||||
BufferOverflow,
|
BufferOverflow,
|
||||||
|
|
||||||
|
/// EVEX payload byte 3 is invalid.
|
||||||
|
InvalidEvexByte3,
|
||||||
|
|
||||||
/// Internal library error.
|
/// Internal library error.
|
||||||
InternalError(u64),
|
InternalError(u64),
|
||||||
}
|
}
|
||||||
@ -181,6 +184,9 @@ impl fmt::Display for DecodeError {
|
|||||||
DecodeError::BufferOverflow => {
|
DecodeError::BufferOverflow => {
|
||||||
write!(f, "not enough space is available to format instruction")
|
write!(f, "not enough space is available to format instruction")
|
||||||
}
|
}
|
||||||
|
DecodeError::InvalidEvexByte3 => {
|
||||||
|
write!(f, "EVEX payload byte 3 is invalid.")
|
||||||
|
}
|
||||||
DecodeError::InternalError(e) => write!(f, "internal error: {}", e),
|
DecodeError::InternalError(e) => write!(f, "internal error: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,6 +238,7 @@ pub(crate) fn status_to_error(status: ffi::NDSTATUS) -> Result<(), DecodeError>
|
|||||||
ffi::ND_STATUS_INVALID_PARAMETER => Err(DecodeError::InvalidParameter),
|
ffi::ND_STATUS_INVALID_PARAMETER => Err(DecodeError::InvalidParameter),
|
||||||
ffi::ND_STATUS_INVALID_INSTRUX => Err(DecodeError::InvalidInstrux),
|
ffi::ND_STATUS_INVALID_INSTRUX => Err(DecodeError::InvalidInstrux),
|
||||||
ffi::ND_STATUS_BUFFER_OVERFLOW => Err(DecodeError::BufferOverflow),
|
ffi::ND_STATUS_BUFFER_OVERFLOW => Err(DecodeError::BufferOverflow),
|
||||||
|
ffi::ND_STATUS_INVALID_EVEX_BYTE3 => Err(DecodeError::InvalidEvexByte3),
|
||||||
ffi::ND_STATUS_INTERNAL_ERROR => Err(DecodeError::InternalError(0)),
|
ffi::ND_STATUS_INTERNAL_ERROR => Err(DecodeError::InternalError(0)),
|
||||||
_ => panic!("Unexpected status: {:#x}", status),
|
_ => panic!("Unexpected status: {:#x}", status),
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,10 +20,11 @@ impl<'a> Decoder<'a> {
|
|||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `code` - An [u8](u8) slice that holds the code to be decoded.
|
/// * `code` - An [`u8`] slice that holds the code to be decoded.
|
||||||
/// * `mode` - The mode in which to decode the instruction.
|
/// * `mode` - The mode in which to decode the instruction.
|
||||||
/// * `ip` - The instruction pointer value to use when formatting the decoded instruction. Does not affect the
|
/// * `ip` - The instruction pointer value to use when formatting the decoded instruction. Does not affect the
|
||||||
/// decoding process in any way.
|
/// decoding process in any way.
|
||||||
|
#[must_use]
|
||||||
pub fn new(code: &'a [u8], mode: DecodeMode, ip: u64) -> Self {
|
pub fn new(code: &'a [u8], mode: DecodeMode, ip: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
code,
|
code,
|
||||||
@ -82,15 +83,12 @@ impl<'a> Decoder<'a> {
|
|||||||
} else {
|
} else {
|
||||||
let result =
|
let result =
|
||||||
DecodedInstruction::decode_with_ip(&self.code[self.offset..], self.mode, self.ip);
|
DecodedInstruction::decode_with_ip(&self.code[self.offset..], self.mode, self.ip);
|
||||||
match result {
|
if let Ok(ins) = result {
|
||||||
Ok(ins) => {
|
self.offset += ins.length();
|
||||||
self.offset += ins.length() as usize;
|
|
||||||
self.ip += ins.length() as u64;
|
self.ip += ins.length() as u64;
|
||||||
}
|
} else {
|
||||||
Err(_) => {
|
|
||||||
self.offset += 1;
|
self.offset += 1;
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(result)
|
Some(result)
|
||||||
@ -99,7 +97,7 @@ impl<'a> Decoder<'a> {
|
|||||||
|
|
||||||
/// Attempts to decode the next instruction from the given code chunk.
|
/// Attempts to decode the next instruction from the given code chunk.
|
||||||
///
|
///
|
||||||
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`](DecodeResult) it
|
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`] it
|
||||||
/// will also return the offset from which decoding was attempted, as well as the corresponding instruction pointer.
|
/// will also return the offset from which decoding was attempted, as well as the corresponding instruction pointer.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -134,7 +132,7 @@ impl<'a> Decoder<'a> {
|
|||||||
|
|
||||||
/// Attempts to decode the next instruction from the given code chunk.
|
/// Attempts to decode the next instruction from the given code chunk.
|
||||||
///
|
///
|
||||||
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`](DecodeResult) it
|
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`] it
|
||||||
/// will also return the offset from which decoding was attempted.
|
/// will also return the offset from which decoding was attempted.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -168,7 +166,7 @@ impl<'a> Decoder<'a> {
|
|||||||
|
|
||||||
/// Attempts to decode the next instruction from the given code chunk.
|
/// Attempts to decode the next instruction from the given code chunk.
|
||||||
///
|
///
|
||||||
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`](DecodeResult) it
|
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`] it
|
||||||
/// will also return the corresponding instruction pointer.
|
/// will also return the corresponding instruction pointer.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
//! Offers information about how an instructions accesses the FPU status registers.
|
//! Offers information about how an instructions accesses the FPU status registers.
|
||||||
|
|
||||||
|
#![allow(clippy::module_name_repetitions)]
|
||||||
|
|
||||||
use super::decode_error::DecodeError;
|
use super::decode_error::DecodeError;
|
||||||
|
|
||||||
/// The mode in which a FPU status flag is accessed.
|
/// The mode in which a FPU status flag is accessed.
|
||||||
|
@ -15,6 +15,7 @@ pub enum Category {
|
|||||||
AES,
|
AES,
|
||||||
AESKL,
|
AESKL,
|
||||||
AMX,
|
AMX,
|
||||||
|
APX,
|
||||||
ARITH,
|
ARITH,
|
||||||
AVX,
|
AVX,
|
||||||
AVX2,
|
AVX2,
|
||||||
@ -72,7 +73,6 @@ pub enum Category {
|
|||||||
MOVDIRI,
|
MOVDIRI,
|
||||||
MPX,
|
MPX,
|
||||||
NOP,
|
NOP,
|
||||||
PADLOCK,
|
|
||||||
PCLMULQDQ,
|
PCLMULQDQ,
|
||||||
PCONFIG,
|
PCONFIG,
|
||||||
POP,
|
POP,
|
||||||
@ -108,6 +108,7 @@ pub enum Category {
|
|||||||
UINTR,
|
UINTR,
|
||||||
UNCOND_BR,
|
UNCOND_BR,
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
USER_MSR,
|
||||||
VAES,
|
VAES,
|
||||||
VFMA,
|
VFMA,
|
||||||
VFMAPS,
|
VFMAPS,
|
||||||
@ -129,6 +130,7 @@ pub enum Category {
|
|||||||
impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
||||||
type Error = DecodeError;
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
fn try_from(value: ffi::ND_INS_CATEGORY) -> Result<Self, Self::Error> {
|
fn try_from(value: ffi::ND_INS_CATEGORY) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_INVALID => Err(DecodeError::InternalError(value as u64)),
|
ffi::_ND_INS_TYPE::ND_CAT_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||||
@ -136,6 +138,7 @@ impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
|||||||
ffi::_ND_INS_TYPE::ND_CAT_AES => Ok(Category::AES),
|
ffi::_ND_INS_TYPE::ND_CAT_AES => Ok(Category::AES),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_AESKL => Ok(Category::AESKL),
|
ffi::_ND_INS_TYPE::ND_CAT_AESKL => Ok(Category::AESKL),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_AMX => Ok(Category::AMX),
|
ffi::_ND_INS_TYPE::ND_CAT_AMX => Ok(Category::AMX),
|
||||||
|
ffi::_ND_INS_TYPE::ND_CAT_APX => Ok(Category::APX),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_ARITH => Ok(Category::ARITH),
|
ffi::_ND_INS_TYPE::ND_CAT_ARITH => Ok(Category::ARITH),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_AVX => Ok(Category::AVX),
|
ffi::_ND_INS_TYPE::ND_CAT_AVX => Ok(Category::AVX),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_AVX2 => Ok(Category::AVX2),
|
ffi::_ND_INS_TYPE::ND_CAT_AVX2 => Ok(Category::AVX2),
|
||||||
@ -193,7 +196,6 @@ impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
|||||||
ffi::_ND_INS_TYPE::ND_CAT_MOVDIRI => Ok(Category::MOVDIRI),
|
ffi::_ND_INS_TYPE::ND_CAT_MOVDIRI => Ok(Category::MOVDIRI),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_MPX => Ok(Category::MPX),
|
ffi::_ND_INS_TYPE::ND_CAT_MPX => Ok(Category::MPX),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_NOP => Ok(Category::NOP),
|
ffi::_ND_INS_TYPE::ND_CAT_NOP => Ok(Category::NOP),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_PADLOCK => Ok(Category::PADLOCK),
|
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_PCLMULQDQ => Ok(Category::PCLMULQDQ),
|
ffi::_ND_INS_TYPE::ND_CAT_PCLMULQDQ => Ok(Category::PCLMULQDQ),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_PCONFIG => Ok(Category::PCONFIG),
|
ffi::_ND_INS_TYPE::ND_CAT_PCONFIG => Ok(Category::PCONFIG),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_POP => Ok(Category::POP),
|
ffi::_ND_INS_TYPE::ND_CAT_POP => Ok(Category::POP),
|
||||||
@ -229,6 +231,7 @@ impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
|||||||
ffi::_ND_INS_TYPE::ND_CAT_UINTR => Ok(Category::UINTR),
|
ffi::_ND_INS_TYPE::ND_CAT_UINTR => Ok(Category::UINTR),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_UNCOND_BR => Ok(Category::UNCOND_BR),
|
ffi::_ND_INS_TYPE::ND_CAT_UNCOND_BR => Ok(Category::UNCOND_BR),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_UNKNOWN => Ok(Category::UNKNOWN),
|
ffi::_ND_INS_TYPE::ND_CAT_UNKNOWN => Ok(Category::UNKNOWN),
|
||||||
|
ffi::_ND_INS_TYPE::ND_CAT_USER_MSR => Ok(Category::USER_MSR),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_VAES => Ok(Category::VAES),
|
ffi::_ND_INS_TYPE::ND_CAT_VAES => Ok(Category::VAES),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_VFMA => Ok(Category::VFMA),
|
ffi::_ND_INS_TYPE::ND_CAT_VFMA => Ok(Category::VFMA),
|
||||||
ffi::_ND_INS_TYPE::ND_CAT_VFMAPS => Ok(Category::VFMAPS),
|
ffi::_ND_INS_TYPE::ND_CAT_VFMAPS => Ok(Category::VFMAPS),
|
||||||
|
@ -20,6 +20,7 @@ pub enum IsaSet {
|
|||||||
AMXFP16,
|
AMXFP16,
|
||||||
AMXINT8,
|
AMXINT8,
|
||||||
AMXTILE,
|
AMXTILE,
|
||||||
|
APX_F,
|
||||||
AVX,
|
AVX,
|
||||||
AVX2,
|
AVX2,
|
||||||
AVX2GATHER,
|
AVX2GATHER,
|
||||||
@ -56,8 +57,6 @@ pub enum IsaSet {
|
|||||||
CLZERO,
|
CLZERO,
|
||||||
CMPCCXADD,
|
CMPCCXADD,
|
||||||
CMPXCHG16B,
|
CMPXCHG16B,
|
||||||
CYRIX,
|
|
||||||
CYRIX_SMM,
|
|
||||||
ENQCMD,
|
ENQCMD,
|
||||||
F16C,
|
F16C,
|
||||||
FMA,
|
FMA,
|
||||||
@ -132,6 +131,7 @@ pub enum IsaSet {
|
|||||||
UD,
|
UD,
|
||||||
UINTR,
|
UINTR,
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
USER_MSR,
|
||||||
VAES,
|
VAES,
|
||||||
VPCLMULQDQ,
|
VPCLMULQDQ,
|
||||||
VTX,
|
VTX,
|
||||||
@ -149,6 +149,7 @@ pub enum IsaSet {
|
|||||||
impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
||||||
type Error = DecodeError;
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
fn try_from(value: ffi::ND_INS_SET) -> Result<Self, Self::Error> {
|
fn try_from(value: ffi::ND_INS_SET) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
ffi::_ND_INS_SET::ND_SET_INVALID => Err(DecodeError::InternalError(value as u64)),
|
ffi::_ND_INS_SET::ND_SET_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||||
@ -161,6 +162,7 @@ impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
|||||||
ffi::_ND_INS_SET::ND_SET_AMXFP16 => Ok(IsaSet::AMXFP16),
|
ffi::_ND_INS_SET::ND_SET_AMXFP16 => Ok(IsaSet::AMXFP16),
|
||||||
ffi::_ND_INS_SET::ND_SET_AMXINT8 => Ok(IsaSet::AMXINT8),
|
ffi::_ND_INS_SET::ND_SET_AMXINT8 => Ok(IsaSet::AMXINT8),
|
||||||
ffi::_ND_INS_SET::ND_SET_AMXTILE => Ok(IsaSet::AMXTILE),
|
ffi::_ND_INS_SET::ND_SET_AMXTILE => Ok(IsaSet::AMXTILE),
|
||||||
|
ffi::_ND_INS_SET::ND_SET_APX_F => Ok(IsaSet::APX_F),
|
||||||
ffi::_ND_INS_SET::ND_SET_AVX => Ok(IsaSet::AVX),
|
ffi::_ND_INS_SET::ND_SET_AVX => Ok(IsaSet::AVX),
|
||||||
ffi::_ND_INS_SET::ND_SET_AVX2 => Ok(IsaSet::AVX2),
|
ffi::_ND_INS_SET::ND_SET_AVX2 => Ok(IsaSet::AVX2),
|
||||||
ffi::_ND_INS_SET::ND_SET_AVX2GATHER => Ok(IsaSet::AVX2GATHER),
|
ffi::_ND_INS_SET::ND_SET_AVX2GATHER => Ok(IsaSet::AVX2GATHER),
|
||||||
@ -197,8 +199,6 @@ impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
|||||||
ffi::_ND_INS_SET::ND_SET_CLZERO => Ok(IsaSet::CLZERO),
|
ffi::_ND_INS_SET::ND_SET_CLZERO => Ok(IsaSet::CLZERO),
|
||||||
ffi::_ND_INS_SET::ND_SET_CMPCCXADD => Ok(IsaSet::CMPCCXADD),
|
ffi::_ND_INS_SET::ND_SET_CMPCCXADD => Ok(IsaSet::CMPCCXADD),
|
||||||
ffi::_ND_INS_SET::ND_SET_CMPXCHG16B => Ok(IsaSet::CMPXCHG16B),
|
ffi::_ND_INS_SET::ND_SET_CMPXCHG16B => Ok(IsaSet::CMPXCHG16B),
|
||||||
ffi::_ND_INS_SET::ND_SET_CYRIX => Ok(IsaSet::CYRIX),
|
|
||||||
ffi::_ND_INS_SET::ND_SET_CYRIX_SMM => Ok(IsaSet::CYRIX_SMM),
|
|
||||||
ffi::_ND_INS_SET::ND_SET_ENQCMD => Ok(IsaSet::ENQCMD),
|
ffi::_ND_INS_SET::ND_SET_ENQCMD => Ok(IsaSet::ENQCMD),
|
||||||
ffi::_ND_INS_SET::ND_SET_F16C => Ok(IsaSet::F16C),
|
ffi::_ND_INS_SET::ND_SET_F16C => Ok(IsaSet::F16C),
|
||||||
ffi::_ND_INS_SET::ND_SET_FMA => Ok(IsaSet::FMA),
|
ffi::_ND_INS_SET::ND_SET_FMA => Ok(IsaSet::FMA),
|
||||||
@ -273,6 +273,7 @@ impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
|||||||
ffi::_ND_INS_SET::ND_SET_UD => Ok(IsaSet::UD),
|
ffi::_ND_INS_SET::ND_SET_UD => Ok(IsaSet::UD),
|
||||||
ffi::_ND_INS_SET::ND_SET_UINTR => Ok(IsaSet::UINTR),
|
ffi::_ND_INS_SET::ND_SET_UINTR => Ok(IsaSet::UINTR),
|
||||||
ffi::_ND_INS_SET::ND_SET_UNKNOWN => Ok(IsaSet::UNKNOWN),
|
ffi::_ND_INS_SET::ND_SET_UNKNOWN => Ok(IsaSet::UNKNOWN),
|
||||||
|
ffi::_ND_INS_SET::ND_SET_USER_MSR => Ok(IsaSet::USER_MSR),
|
||||||
ffi::_ND_INS_SET::ND_SET_VAES => Ok(IsaSet::VAES),
|
ffi::_ND_INS_SET::ND_SET_VAES => Ok(IsaSet::VAES),
|
||||||
ffi::_ND_INS_SET::ND_SET_VPCLMULQDQ => Ok(IsaSet::VPCLMULQDQ),
|
ffi::_ND_INS_SET::ND_SET_VPCLMULQDQ => Ok(IsaSet::VPCLMULQDQ),
|
||||||
ffi::_ND_INS_SET::ND_SET_VTX => Ok(IsaSet::VTX),
|
ffi::_ND_INS_SET::ND_SET_VTX => Ok(IsaSet::VTX),
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! [dependencies]
|
//! [dependencies]
|
||||||
//! bddisasm = "0.1.0"
|
//! bddisasm = "0.2"
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
@ -47,7 +47,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Decoding multiple instructions
|
//! ## Decoding multiple instructions
|
||||||
//!
|
//!
|
||||||
//! Use [`Decoder`](crate::decoder::Decoder) to decode multiple instructions from a chunk of code.
|
//! Use [`Decoder`] to decode multiple instructions from a chunk of code.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use bddisasm::{Decoder, DecodeMode};
|
//! use bddisasm::{Decoder, DecodeMode};
|
||||||
@ -120,7 +120,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Working with instruction operands
|
//! ## Working with instruction operands
|
||||||
//!
|
//!
|
||||||
//! Instruction operands can be analyzed using the [operand](crate::operand) module. Rich informaion is offered for
|
//! Instruction operands can be analyzed using the [`operand`] module. Rich informaion is offered for
|
||||||
//! each type of operand. Bellow is a minimal example that looks at a memory operand.
|
//! each type of operand. Bellow is a minimal example that looks at a memory operand.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
@ -190,6 +190,7 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
||||||
|
#![allow(clippy::if_not_else)]
|
||||||
|
|
||||||
pub extern crate bddisasm_sys as ffi;
|
pub extern crate bddisasm_sys as ffi;
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ pub enum Mnemonic {
|
|||||||
AESENCWIDE256KL,
|
AESENCWIDE256KL,
|
||||||
AESIMC,
|
AESIMC,
|
||||||
AESKEYGENASSIST,
|
AESKEYGENASSIST,
|
||||||
ALTINST,
|
|
||||||
AND,
|
AND,
|
||||||
ANDN,
|
ANDN,
|
||||||
ANDNPD,
|
ANDNPD,
|
||||||
@ -87,8 +86,10 @@ pub enum Mnemonic {
|
|||||||
CALLNI,
|
CALLNI,
|
||||||
CALLNR,
|
CALLNR,
|
||||||
CBW,
|
CBW,
|
||||||
|
CCMP,
|
||||||
CDQ,
|
CDQ,
|
||||||
CDQE,
|
CDQE,
|
||||||
|
CFCMOV,
|
||||||
CLAC,
|
CLAC,
|
||||||
CLC,
|
CLC,
|
||||||
CLD,
|
CLD,
|
||||||
@ -134,10 +135,9 @@ pub enum Mnemonic {
|
|||||||
COMISD,
|
COMISD,
|
||||||
COMISS,
|
COMISS,
|
||||||
CPUID,
|
CPUID,
|
||||||
CPU_READ,
|
|
||||||
CPU_WRITE,
|
|
||||||
CQO,
|
CQO,
|
||||||
CRC32,
|
CRC32,
|
||||||
|
CTEST,
|
||||||
CVTDQ2PD,
|
CVTDQ2PD,
|
||||||
CVTDQ2PS,
|
CVTDQ2PS,
|
||||||
CVTPD2DQ,
|
CVTPD2DQ,
|
||||||
@ -171,7 +171,6 @@ pub enum Mnemonic {
|
|||||||
DIVPS,
|
DIVPS,
|
||||||
DIVSD,
|
DIVSD,
|
||||||
DIVSS,
|
DIVSS,
|
||||||
DMINT,
|
|
||||||
DPPD,
|
DPPD,
|
||||||
DPPS,
|
DPPS,
|
||||||
EMMS,
|
EMMS,
|
||||||
@ -315,6 +314,7 @@ pub enum Mnemonic {
|
|||||||
INVPCID,
|
INVPCID,
|
||||||
INVVPID,
|
INVVPID,
|
||||||
IRET,
|
IRET,
|
||||||
|
JMPABS,
|
||||||
JMPE,
|
JMPE,
|
||||||
JMPFD,
|
JMPFD,
|
||||||
JMPFI,
|
JMPFI,
|
||||||
@ -382,7 +382,6 @@ pub enum Mnemonic {
|
|||||||
MINSS,
|
MINSS,
|
||||||
MONITOR,
|
MONITOR,
|
||||||
MONITORX,
|
MONITORX,
|
||||||
MONTMUL,
|
|
||||||
MOV,
|
MOV,
|
||||||
MOVAPD,
|
MOVAPD,
|
||||||
MOVAPS,
|
MOVAPS,
|
||||||
@ -557,10 +556,13 @@ pub enum Mnemonic {
|
|||||||
PMULLW,
|
PMULLW,
|
||||||
PMULUDQ,
|
PMULUDQ,
|
||||||
POP,
|
POP,
|
||||||
|
POP2,
|
||||||
|
POP2P,
|
||||||
POPA,
|
POPA,
|
||||||
POPAD,
|
POPAD,
|
||||||
POPCNT,
|
POPCNT,
|
||||||
POPF,
|
POPF,
|
||||||
|
POPP,
|
||||||
POR,
|
POR,
|
||||||
PREFETCH,
|
PREFETCH,
|
||||||
PREFETCHE,
|
PREFETCHE,
|
||||||
@ -613,9 +615,12 @@ pub enum Mnemonic {
|
|||||||
PUNPCKLQDQ,
|
PUNPCKLQDQ,
|
||||||
PUNPCKLWD,
|
PUNPCKLWD,
|
||||||
PUSH,
|
PUSH,
|
||||||
|
PUSH2,
|
||||||
|
PUSH2P,
|
||||||
PUSHA,
|
PUSHA,
|
||||||
PUSHAD,
|
PUSHAD,
|
||||||
PUSHF,
|
PUSHF,
|
||||||
|
PUSHP,
|
||||||
PVALIDATE,
|
PVALIDATE,
|
||||||
PXOR,
|
PXOR,
|
||||||
RCL,
|
RCL,
|
||||||
@ -632,7 +637,6 @@ pub enum Mnemonic {
|
|||||||
RDPRU,
|
RDPRU,
|
||||||
RDRAND,
|
RDRAND,
|
||||||
RDSEED,
|
RDSEED,
|
||||||
RDSHR,
|
|
||||||
RDTSC,
|
RDTSC,
|
||||||
RDTSCP,
|
RDTSCP,
|
||||||
RETF,
|
RETF,
|
||||||
@ -647,14 +651,11 @@ pub enum Mnemonic {
|
|||||||
ROUNDPS,
|
ROUNDPS,
|
||||||
ROUNDSD,
|
ROUNDSD,
|
||||||
ROUNDSS,
|
ROUNDSS,
|
||||||
RSDC,
|
|
||||||
RSLDT,
|
|
||||||
RSM,
|
RSM,
|
||||||
RSQRTPS,
|
RSQRTPS,
|
||||||
RSQRTSS,
|
RSQRTSS,
|
||||||
RSSSP,
|
RSSSP,
|
||||||
RSTORSSP,
|
RSTORSSP,
|
||||||
RSTS,
|
|
||||||
SAHF,
|
SAHF,
|
||||||
SAL,
|
SAL,
|
||||||
SALC,
|
SALC,
|
||||||
@ -691,7 +692,6 @@ pub enum Mnemonic {
|
|||||||
SKINIT,
|
SKINIT,
|
||||||
SLDT,
|
SLDT,
|
||||||
SLWPCB,
|
SLWPCB,
|
||||||
SMINT,
|
|
||||||
SMSW,
|
SMSW,
|
||||||
SPFLT,
|
SPFLT,
|
||||||
SQRTPD,
|
SQRTPD,
|
||||||
@ -713,9 +713,6 @@ pub enum Mnemonic {
|
|||||||
SUBPS,
|
SUBPS,
|
||||||
SUBSD,
|
SUBSD,
|
||||||
SUBSS,
|
SUBSS,
|
||||||
SVDC,
|
|
||||||
SVLDT,
|
|
||||||
SVTS,
|
|
||||||
SWAPGS,
|
SWAPGS,
|
||||||
SYSCALL,
|
SYSCALL,
|
||||||
SYSENTER,
|
SYSENTER,
|
||||||
@ -754,6 +751,8 @@ pub enum Mnemonic {
|
|||||||
UNPCKHPS,
|
UNPCKHPS,
|
||||||
UNPCKLPD,
|
UNPCKLPD,
|
||||||
UNPCKLPS,
|
UNPCKLPS,
|
||||||
|
URDMSR,
|
||||||
|
UWRMSR,
|
||||||
V4FMADDPS,
|
V4FMADDPS,
|
||||||
V4FMADDSS,
|
V4FMADDSS,
|
||||||
V4FNMADDPS,
|
V4FNMADDPS,
|
||||||
@ -1621,18 +1620,12 @@ pub enum Mnemonic {
|
|||||||
WRMSRLIST,
|
WRMSRLIST,
|
||||||
WRMSRNS,
|
WRMSRNS,
|
||||||
WRPKRU,
|
WRPKRU,
|
||||||
WRSHR,
|
|
||||||
WRSS,
|
WRSS,
|
||||||
WRUSS,
|
WRUSS,
|
||||||
XABORT,
|
XABORT,
|
||||||
XADD,
|
XADD,
|
||||||
XBEGIN,
|
XBEGIN,
|
||||||
XCHG,
|
XCHG,
|
||||||
XCRYPTCBC,
|
|
||||||
XCRYPTCFB,
|
|
||||||
XCRYPTCTR,
|
|
||||||
XCRYPTECB,
|
|
||||||
XCRYPTOFB,
|
|
||||||
XEND,
|
XEND,
|
||||||
XGETBV,
|
XGETBV,
|
||||||
XLATB,
|
XLATB,
|
||||||
@ -1647,9 +1640,6 @@ pub enum Mnemonic {
|
|||||||
XSAVEOPT,
|
XSAVEOPT,
|
||||||
XSAVES,
|
XSAVES,
|
||||||
XSETBV,
|
XSETBV,
|
||||||
XSHA1,
|
|
||||||
XSHA256,
|
|
||||||
XSTORE,
|
|
||||||
XSUSLDTRK,
|
XSUSLDTRK,
|
||||||
XTEST,
|
XTEST,
|
||||||
}
|
}
|
||||||
@ -1658,6 +1648,7 @@ pub enum Mnemonic {
|
|||||||
impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
||||||
type Error = DecodeError;
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
fn try_from(value: ffi::ND_INS_CLASS) -> Result<Self, Self::Error> {
|
fn try_from(value: ffi::ND_INS_CLASS) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
ffi::_ND_INS_CLASS::ND_INS_INVALID => Err(DecodeError::InternalError(value as u64)),
|
ffi::_ND_INS_CLASS::ND_INS_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||||
@ -1691,7 +1682,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_AESENCWIDE256KL => Ok(Mnemonic::AESENCWIDE256KL),
|
ffi::_ND_INS_CLASS::ND_INS_AESENCWIDE256KL => Ok(Mnemonic::AESENCWIDE256KL),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_AESIMC => Ok(Mnemonic::AESIMC),
|
ffi::_ND_INS_CLASS::ND_INS_AESIMC => Ok(Mnemonic::AESIMC),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_AESKEYGENASSIST => Ok(Mnemonic::AESKEYGENASSIST),
|
ffi::_ND_INS_CLASS::ND_INS_AESKEYGENASSIST => Ok(Mnemonic::AESKEYGENASSIST),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_ALTINST => Ok(Mnemonic::ALTINST),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_AND => Ok(Mnemonic::AND),
|
ffi::_ND_INS_CLASS::ND_INS_AND => Ok(Mnemonic::AND),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_ANDN => Ok(Mnemonic::ANDN),
|
ffi::_ND_INS_CLASS::ND_INS_ANDN => Ok(Mnemonic::ANDN),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_ANDNPD => Ok(Mnemonic::ANDNPD),
|
ffi::_ND_INS_CLASS::ND_INS_ANDNPD => Ok(Mnemonic::ANDNPD),
|
||||||
@ -1737,8 +1727,10 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_CALLNI => Ok(Mnemonic::CALLNI),
|
ffi::_ND_INS_CLASS::ND_INS_CALLNI => Ok(Mnemonic::CALLNI),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CALLNR => Ok(Mnemonic::CALLNR),
|
ffi::_ND_INS_CLASS::ND_INS_CALLNR => Ok(Mnemonic::CALLNR),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CBW => Ok(Mnemonic::CBW),
|
ffi::_ND_INS_CLASS::ND_INS_CBW => Ok(Mnemonic::CBW),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_CCMP => Ok(Mnemonic::CCMP),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CDQ => Ok(Mnemonic::CDQ),
|
ffi::_ND_INS_CLASS::ND_INS_CDQ => Ok(Mnemonic::CDQ),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CDQE => Ok(Mnemonic::CDQE),
|
ffi::_ND_INS_CLASS::ND_INS_CDQE => Ok(Mnemonic::CDQE),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_CFCMOV => Ok(Mnemonic::CFCMOV),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CLAC => Ok(Mnemonic::CLAC),
|
ffi::_ND_INS_CLASS::ND_INS_CLAC => Ok(Mnemonic::CLAC),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CLC => Ok(Mnemonic::CLC),
|
ffi::_ND_INS_CLASS::ND_INS_CLC => Ok(Mnemonic::CLC),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CLD => Ok(Mnemonic::CLD),
|
ffi::_ND_INS_CLASS::ND_INS_CLD => Ok(Mnemonic::CLD),
|
||||||
@ -1784,10 +1776,9 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_COMISD => Ok(Mnemonic::COMISD),
|
ffi::_ND_INS_CLASS::ND_INS_COMISD => Ok(Mnemonic::COMISD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_COMISS => Ok(Mnemonic::COMISS),
|
ffi::_ND_INS_CLASS::ND_INS_COMISS => Ok(Mnemonic::COMISS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CPUID => Ok(Mnemonic::CPUID),
|
ffi::_ND_INS_CLASS::ND_INS_CPUID => Ok(Mnemonic::CPUID),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CPU_READ => Ok(Mnemonic::CPU_READ),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CPU_WRITE => Ok(Mnemonic::CPU_WRITE),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CQO => Ok(Mnemonic::CQO),
|
ffi::_ND_INS_CLASS::ND_INS_CQO => Ok(Mnemonic::CQO),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CRC32 => Ok(Mnemonic::CRC32),
|
ffi::_ND_INS_CLASS::ND_INS_CRC32 => Ok(Mnemonic::CRC32),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_CTEST => Ok(Mnemonic::CTEST),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CVTDQ2PD => Ok(Mnemonic::CVTDQ2PD),
|
ffi::_ND_INS_CLASS::ND_INS_CVTDQ2PD => Ok(Mnemonic::CVTDQ2PD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CVTDQ2PS => Ok(Mnemonic::CVTDQ2PS),
|
ffi::_ND_INS_CLASS::ND_INS_CVTDQ2PS => Ok(Mnemonic::CVTDQ2PS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_CVTPD2DQ => Ok(Mnemonic::CVTPD2DQ),
|
ffi::_ND_INS_CLASS::ND_INS_CVTPD2DQ => Ok(Mnemonic::CVTPD2DQ),
|
||||||
@ -1821,7 +1812,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_DIVPS => Ok(Mnemonic::DIVPS),
|
ffi::_ND_INS_CLASS::ND_INS_DIVPS => Ok(Mnemonic::DIVPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_DIVSD => Ok(Mnemonic::DIVSD),
|
ffi::_ND_INS_CLASS::ND_INS_DIVSD => Ok(Mnemonic::DIVSD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_DIVSS => Ok(Mnemonic::DIVSS),
|
ffi::_ND_INS_CLASS::ND_INS_DIVSS => Ok(Mnemonic::DIVSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_DMINT => Ok(Mnemonic::DMINT),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_DPPD => Ok(Mnemonic::DPPD),
|
ffi::_ND_INS_CLASS::ND_INS_DPPD => Ok(Mnemonic::DPPD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_DPPS => Ok(Mnemonic::DPPS),
|
ffi::_ND_INS_CLASS::ND_INS_DPPS => Ok(Mnemonic::DPPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_EMMS => Ok(Mnemonic::EMMS),
|
ffi::_ND_INS_CLASS::ND_INS_EMMS => Ok(Mnemonic::EMMS),
|
||||||
@ -1965,6 +1955,7 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_INVPCID => Ok(Mnemonic::INVPCID),
|
ffi::_ND_INS_CLASS::ND_INS_INVPCID => Ok(Mnemonic::INVPCID),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_INVVPID => Ok(Mnemonic::INVVPID),
|
ffi::_ND_INS_CLASS::ND_INS_INVVPID => Ok(Mnemonic::INVVPID),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_IRET => Ok(Mnemonic::IRET),
|
ffi::_ND_INS_CLASS::ND_INS_IRET => Ok(Mnemonic::IRET),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_JMPABS => Ok(Mnemonic::JMPABS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_JMPE => Ok(Mnemonic::JMPE),
|
ffi::_ND_INS_CLASS::ND_INS_JMPE => Ok(Mnemonic::JMPE),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_JMPFD => Ok(Mnemonic::JMPFD),
|
ffi::_ND_INS_CLASS::ND_INS_JMPFD => Ok(Mnemonic::JMPFD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_JMPFI => Ok(Mnemonic::JMPFI),
|
ffi::_ND_INS_CLASS::ND_INS_JMPFI => Ok(Mnemonic::JMPFI),
|
||||||
@ -2032,7 +2023,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_MINSS => Ok(Mnemonic::MINSS),
|
ffi::_ND_INS_CLASS::ND_INS_MINSS => Ok(Mnemonic::MINSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_MONITOR => Ok(Mnemonic::MONITOR),
|
ffi::_ND_INS_CLASS::ND_INS_MONITOR => Ok(Mnemonic::MONITOR),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_MONITORX => Ok(Mnemonic::MONITORX),
|
ffi::_ND_INS_CLASS::ND_INS_MONITORX => Ok(Mnemonic::MONITORX),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_MONTMUL => Ok(Mnemonic::MONTMUL),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_MOV => Ok(Mnemonic::MOV),
|
ffi::_ND_INS_CLASS::ND_INS_MOV => Ok(Mnemonic::MOV),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_MOVAPD => Ok(Mnemonic::MOVAPD),
|
ffi::_ND_INS_CLASS::ND_INS_MOVAPD => Ok(Mnemonic::MOVAPD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_MOVAPS => Ok(Mnemonic::MOVAPS),
|
ffi::_ND_INS_CLASS::ND_INS_MOVAPS => Ok(Mnemonic::MOVAPS),
|
||||||
@ -2207,10 +2197,13 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_PMULLW => Ok(Mnemonic::PMULLW),
|
ffi::_ND_INS_CLASS::ND_INS_PMULLW => Ok(Mnemonic::PMULLW),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PMULUDQ => Ok(Mnemonic::PMULUDQ),
|
ffi::_ND_INS_CLASS::ND_INS_PMULUDQ => Ok(Mnemonic::PMULUDQ),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_POP => Ok(Mnemonic::POP),
|
ffi::_ND_INS_CLASS::ND_INS_POP => Ok(Mnemonic::POP),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_POP2 => Ok(Mnemonic::POP2),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_POP2P => Ok(Mnemonic::POP2P),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_POPA => Ok(Mnemonic::POPA),
|
ffi::_ND_INS_CLASS::ND_INS_POPA => Ok(Mnemonic::POPA),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_POPAD => Ok(Mnemonic::POPAD),
|
ffi::_ND_INS_CLASS::ND_INS_POPAD => Ok(Mnemonic::POPAD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_POPCNT => Ok(Mnemonic::POPCNT),
|
ffi::_ND_INS_CLASS::ND_INS_POPCNT => Ok(Mnemonic::POPCNT),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_POPF => Ok(Mnemonic::POPF),
|
ffi::_ND_INS_CLASS::ND_INS_POPF => Ok(Mnemonic::POPF),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_POPP => Ok(Mnemonic::POPP),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_POR => Ok(Mnemonic::POR),
|
ffi::_ND_INS_CLASS::ND_INS_POR => Ok(Mnemonic::POR),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PREFETCH => Ok(Mnemonic::PREFETCH),
|
ffi::_ND_INS_CLASS::ND_INS_PREFETCH => Ok(Mnemonic::PREFETCH),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PREFETCHE => Ok(Mnemonic::PREFETCHE),
|
ffi::_ND_INS_CLASS::ND_INS_PREFETCHE => Ok(Mnemonic::PREFETCHE),
|
||||||
@ -2263,9 +2256,12 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_PUNPCKLQDQ => Ok(Mnemonic::PUNPCKLQDQ),
|
ffi::_ND_INS_CLASS::ND_INS_PUNPCKLQDQ => Ok(Mnemonic::PUNPCKLQDQ),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PUNPCKLWD => Ok(Mnemonic::PUNPCKLWD),
|
ffi::_ND_INS_CLASS::ND_INS_PUNPCKLWD => Ok(Mnemonic::PUNPCKLWD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PUSH => Ok(Mnemonic::PUSH),
|
ffi::_ND_INS_CLASS::ND_INS_PUSH => Ok(Mnemonic::PUSH),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_PUSH2 => Ok(Mnemonic::PUSH2),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_PUSH2P => Ok(Mnemonic::PUSH2P),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PUSHA => Ok(Mnemonic::PUSHA),
|
ffi::_ND_INS_CLASS::ND_INS_PUSHA => Ok(Mnemonic::PUSHA),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PUSHAD => Ok(Mnemonic::PUSHAD),
|
ffi::_ND_INS_CLASS::ND_INS_PUSHAD => Ok(Mnemonic::PUSHAD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PUSHF => Ok(Mnemonic::PUSHF),
|
ffi::_ND_INS_CLASS::ND_INS_PUSHF => Ok(Mnemonic::PUSHF),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_PUSHP => Ok(Mnemonic::PUSHP),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PVALIDATE => Ok(Mnemonic::PVALIDATE),
|
ffi::_ND_INS_CLASS::ND_INS_PVALIDATE => Ok(Mnemonic::PVALIDATE),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_PXOR => Ok(Mnemonic::PXOR),
|
ffi::_ND_INS_CLASS::ND_INS_PXOR => Ok(Mnemonic::PXOR),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RCL => Ok(Mnemonic::RCL),
|
ffi::_ND_INS_CLASS::ND_INS_RCL => Ok(Mnemonic::RCL),
|
||||||
@ -2282,7 +2278,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_RDPRU => Ok(Mnemonic::RDPRU),
|
ffi::_ND_INS_CLASS::ND_INS_RDPRU => Ok(Mnemonic::RDPRU),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RDRAND => Ok(Mnemonic::RDRAND),
|
ffi::_ND_INS_CLASS::ND_INS_RDRAND => Ok(Mnemonic::RDRAND),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RDSEED => Ok(Mnemonic::RDSEED),
|
ffi::_ND_INS_CLASS::ND_INS_RDSEED => Ok(Mnemonic::RDSEED),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RDSHR => Ok(Mnemonic::RDSHR),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RDTSC => Ok(Mnemonic::RDTSC),
|
ffi::_ND_INS_CLASS::ND_INS_RDTSC => Ok(Mnemonic::RDTSC),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RDTSCP => Ok(Mnemonic::RDTSCP),
|
ffi::_ND_INS_CLASS::ND_INS_RDTSCP => Ok(Mnemonic::RDTSCP),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RETF => Ok(Mnemonic::RETF),
|
ffi::_ND_INS_CLASS::ND_INS_RETF => Ok(Mnemonic::RETF),
|
||||||
@ -2297,14 +2292,11 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_ROUNDPS => Ok(Mnemonic::ROUNDPS),
|
ffi::_ND_INS_CLASS::ND_INS_ROUNDPS => Ok(Mnemonic::ROUNDPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_ROUNDSD => Ok(Mnemonic::ROUNDSD),
|
ffi::_ND_INS_CLASS::ND_INS_ROUNDSD => Ok(Mnemonic::ROUNDSD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_ROUNDSS => Ok(Mnemonic::ROUNDSS),
|
ffi::_ND_INS_CLASS::ND_INS_ROUNDSS => Ok(Mnemonic::ROUNDSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSDC => Ok(Mnemonic::RSDC),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSLDT => Ok(Mnemonic::RSLDT),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSM => Ok(Mnemonic::RSM),
|
ffi::_ND_INS_CLASS::ND_INS_RSM => Ok(Mnemonic::RSM),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSQRTPS => Ok(Mnemonic::RSQRTPS),
|
ffi::_ND_INS_CLASS::ND_INS_RSQRTPS => Ok(Mnemonic::RSQRTPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSQRTSS => Ok(Mnemonic::RSQRTSS),
|
ffi::_ND_INS_CLASS::ND_INS_RSQRTSS => Ok(Mnemonic::RSQRTSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSSSP => Ok(Mnemonic::RSSSP),
|
ffi::_ND_INS_CLASS::ND_INS_RSSSP => Ok(Mnemonic::RSSSP),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSTORSSP => Ok(Mnemonic::RSTORSSP),
|
ffi::_ND_INS_CLASS::ND_INS_RSTORSSP => Ok(Mnemonic::RSTORSSP),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_RSTS => Ok(Mnemonic::RSTS),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SAHF => Ok(Mnemonic::SAHF),
|
ffi::_ND_INS_CLASS::ND_INS_SAHF => Ok(Mnemonic::SAHF),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SAL => Ok(Mnemonic::SAL),
|
ffi::_ND_INS_CLASS::ND_INS_SAL => Ok(Mnemonic::SAL),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SALC => Ok(Mnemonic::SALC),
|
ffi::_ND_INS_CLASS::ND_INS_SALC => Ok(Mnemonic::SALC),
|
||||||
@ -2341,7 +2333,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_SKINIT => Ok(Mnemonic::SKINIT),
|
ffi::_ND_INS_CLASS::ND_INS_SKINIT => Ok(Mnemonic::SKINIT),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SLDT => Ok(Mnemonic::SLDT),
|
ffi::_ND_INS_CLASS::ND_INS_SLDT => Ok(Mnemonic::SLDT),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SLWPCB => Ok(Mnemonic::SLWPCB),
|
ffi::_ND_INS_CLASS::ND_INS_SLWPCB => Ok(Mnemonic::SLWPCB),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SMINT => Ok(Mnemonic::SMINT),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SMSW => Ok(Mnemonic::SMSW),
|
ffi::_ND_INS_CLASS::ND_INS_SMSW => Ok(Mnemonic::SMSW),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SPFLT => Ok(Mnemonic::SPFLT),
|
ffi::_ND_INS_CLASS::ND_INS_SPFLT => Ok(Mnemonic::SPFLT),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SQRTPD => Ok(Mnemonic::SQRTPD),
|
ffi::_ND_INS_CLASS::ND_INS_SQRTPD => Ok(Mnemonic::SQRTPD),
|
||||||
@ -2363,9 +2354,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_SUBPS => Ok(Mnemonic::SUBPS),
|
ffi::_ND_INS_CLASS::ND_INS_SUBPS => Ok(Mnemonic::SUBPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SUBSD => Ok(Mnemonic::SUBSD),
|
ffi::_ND_INS_CLASS::ND_INS_SUBSD => Ok(Mnemonic::SUBSD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SUBSS => Ok(Mnemonic::SUBSS),
|
ffi::_ND_INS_CLASS::ND_INS_SUBSS => Ok(Mnemonic::SUBSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SVDC => Ok(Mnemonic::SVDC),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SVLDT => Ok(Mnemonic::SVLDT),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SVTS => Ok(Mnemonic::SVTS),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SWAPGS => Ok(Mnemonic::SWAPGS),
|
ffi::_ND_INS_CLASS::ND_INS_SWAPGS => Ok(Mnemonic::SWAPGS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SYSCALL => Ok(Mnemonic::SYSCALL),
|
ffi::_ND_INS_CLASS::ND_INS_SYSCALL => Ok(Mnemonic::SYSCALL),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_SYSENTER => Ok(Mnemonic::SYSENTER),
|
ffi::_ND_INS_CLASS::ND_INS_SYSENTER => Ok(Mnemonic::SYSENTER),
|
||||||
@ -2404,6 +2392,8 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_UNPCKHPS => Ok(Mnemonic::UNPCKHPS),
|
ffi::_ND_INS_CLASS::ND_INS_UNPCKHPS => Ok(Mnemonic::UNPCKHPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_UNPCKLPD => Ok(Mnemonic::UNPCKLPD),
|
ffi::_ND_INS_CLASS::ND_INS_UNPCKLPD => Ok(Mnemonic::UNPCKLPD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_UNPCKLPS => Ok(Mnemonic::UNPCKLPS),
|
ffi::_ND_INS_CLASS::ND_INS_UNPCKLPS => Ok(Mnemonic::UNPCKLPS),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_URDMSR => Ok(Mnemonic::URDMSR),
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_UWRMSR => Ok(Mnemonic::UWRMSR),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_V4FMADDPS => Ok(Mnemonic::V4FMADDPS),
|
ffi::_ND_INS_CLASS::ND_INS_V4FMADDPS => Ok(Mnemonic::V4FMADDPS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_V4FMADDSS => Ok(Mnemonic::V4FMADDSS),
|
ffi::_ND_INS_CLASS::ND_INS_V4FMADDSS => Ok(Mnemonic::V4FMADDSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_V4FNMADDPS => Ok(Mnemonic::V4FNMADDPS),
|
ffi::_ND_INS_CLASS::ND_INS_V4FNMADDPS => Ok(Mnemonic::V4FNMADDPS),
|
||||||
@ -3271,18 +3261,12 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_WRMSRLIST => Ok(Mnemonic::WRMSRLIST),
|
ffi::_ND_INS_CLASS::ND_INS_WRMSRLIST => Ok(Mnemonic::WRMSRLIST),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_WRMSRNS => Ok(Mnemonic::WRMSRNS),
|
ffi::_ND_INS_CLASS::ND_INS_WRMSRNS => Ok(Mnemonic::WRMSRNS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_WRPKRU => Ok(Mnemonic::WRPKRU),
|
ffi::_ND_INS_CLASS::ND_INS_WRPKRU => Ok(Mnemonic::WRPKRU),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_WRSHR => Ok(Mnemonic::WRSHR),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_WRSS => Ok(Mnemonic::WRSS),
|
ffi::_ND_INS_CLASS::ND_INS_WRSS => Ok(Mnemonic::WRSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_WRUSS => Ok(Mnemonic::WRUSS),
|
ffi::_ND_INS_CLASS::ND_INS_WRUSS => Ok(Mnemonic::WRUSS),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XABORT => Ok(Mnemonic::XABORT),
|
ffi::_ND_INS_CLASS::ND_INS_XABORT => Ok(Mnemonic::XABORT),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XADD => Ok(Mnemonic::XADD),
|
ffi::_ND_INS_CLASS::ND_INS_XADD => Ok(Mnemonic::XADD),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XBEGIN => Ok(Mnemonic::XBEGIN),
|
ffi::_ND_INS_CLASS::ND_INS_XBEGIN => Ok(Mnemonic::XBEGIN),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XCHG => Ok(Mnemonic::XCHG),
|
ffi::_ND_INS_CLASS::ND_INS_XCHG => Ok(Mnemonic::XCHG),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XCRYPTCBC => Ok(Mnemonic::XCRYPTCBC),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XCRYPTCFB => Ok(Mnemonic::XCRYPTCFB),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XCRYPTCTR => Ok(Mnemonic::XCRYPTCTR),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XCRYPTECB => Ok(Mnemonic::XCRYPTECB),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XCRYPTOFB => Ok(Mnemonic::XCRYPTOFB),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XEND => Ok(Mnemonic::XEND),
|
ffi::_ND_INS_CLASS::ND_INS_XEND => Ok(Mnemonic::XEND),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XGETBV => Ok(Mnemonic::XGETBV),
|
ffi::_ND_INS_CLASS::ND_INS_XGETBV => Ok(Mnemonic::XGETBV),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XLATB => Ok(Mnemonic::XLATB),
|
ffi::_ND_INS_CLASS::ND_INS_XLATB => Ok(Mnemonic::XLATB),
|
||||||
@ -3297,9 +3281,6 @@ impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
|||||||
ffi::_ND_INS_CLASS::ND_INS_XSAVEOPT => Ok(Mnemonic::XSAVEOPT),
|
ffi::_ND_INS_CLASS::ND_INS_XSAVEOPT => Ok(Mnemonic::XSAVEOPT),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XSAVES => Ok(Mnemonic::XSAVES),
|
ffi::_ND_INS_CLASS::ND_INS_XSAVES => Ok(Mnemonic::XSAVES),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XSETBV => Ok(Mnemonic::XSETBV),
|
ffi::_ND_INS_CLASS::ND_INS_XSETBV => Ok(Mnemonic::XSETBV),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XSHA1 => Ok(Mnemonic::XSHA1),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XSHA256 => Ok(Mnemonic::XSHA256),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XSTORE => Ok(Mnemonic::XSTORE),
|
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XSUSLDTRK => Ok(Mnemonic::XSUSLDTRK),
|
ffi::_ND_INS_CLASS::ND_INS_XSUSLDTRK => Ok(Mnemonic::XSUSLDTRK),
|
||||||
ffi::_ND_INS_CLASS::ND_INS_XTEST => Ok(Mnemonic::XTEST),
|
ffi::_ND_INS_CLASS::ND_INS_XTEST => Ok(Mnemonic::XTEST),
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,6 @@ impl OpAddr {
|
|||||||
offset: raw.Offset,
|
offset: raw.Offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(base_seg: u16, offset: u64) -> Self {
|
|
||||||
Self { base_seg, offset }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of a register.
|
/// The type of a register.
|
||||||
@ -188,7 +184,7 @@ pub struct OpReg {
|
|||||||
///
|
///
|
||||||
/// # Remarks
|
/// # Remarks
|
||||||
///
|
///
|
||||||
/// If [kind](OpReg::kind) is [OpRegType::Gpr](OpRegType::Gpr), the high and low part of 16-bit registers will have
|
/// If [kind](OpReg::kind) is [`OpRegType::Gpr`], the high and low part of 16-bit registers will have
|
||||||
/// the same index (for example, `AH` and `AL`). To differentiate between them use [is_high8](OpReg::is_high8).
|
/// the same index (for example, `AH` and `AL`). To differentiate between them use [is_high8](OpReg::is_high8).
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
|
|
||||||
@ -223,7 +219,7 @@ impl OpReg {
|
|||||||
kind,
|
kind,
|
||||||
size: raw.Size,
|
size: raw.Size,
|
||||||
index,
|
index,
|
||||||
count: raw.Count,
|
count: raw.Count as u32,
|
||||||
is_high8,
|
is_high8,
|
||||||
is_block: raw.IsBlock() != 0,
|
is_block: raw.IsBlock() != 0,
|
||||||
})
|
})
|
||||||
@ -279,6 +275,7 @@ impl ShadowStackAccess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Describes a memory operand.
|
/// Describes a memory operand.
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct OpMem {
|
pub struct OpMem {
|
||||||
/// `true` if the memory operand is a broadcast operand.
|
/// `true` if the memory operand is a broadcast operand.
|
||||||
@ -353,19 +350,23 @@ pub struct OpMem {
|
|||||||
impl OpMem {
|
impl OpMem {
|
||||||
pub(crate) fn from_raw(raw: ffi::ND_OPDESC_MEMORY) -> Result<Self, DecodeError> {
|
pub(crate) fn from_raw(raw: ffi::ND_OPDESC_MEMORY) -> Result<Self, DecodeError> {
|
||||||
let seg = if raw.HasSeg() != 0 {
|
let seg = if raw.HasSeg() != 0 {
|
||||||
Some(raw.Seg)
|
Some(raw.Seg())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let (base, base_size) = if raw.HasBase() != 0 {
|
let (base, base_size) = if raw.HasBase() != 0 {
|
||||||
(Some(raw.Base), Some(raw.BaseSize))
|
(Some(raw.Base()), Some(raw.BaseSize as u32))
|
||||||
} else {
|
} else {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (index, index_size, scale) = if raw.HasIndex() != 0 {
|
let (index, index_size, scale) = if raw.HasIndex() != 0 {
|
||||||
(Some(raw.Index), Some(raw.IndexSize), Some(raw.Scale))
|
(
|
||||||
|
Some(raw.Index),
|
||||||
|
Some(raw.IndexSize as u32),
|
||||||
|
Some(raw.Scale()),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
(None, None, None)
|
(None, None, None)
|
||||||
};
|
};
|
||||||
@ -385,10 +386,10 @@ impl OpMem {
|
|||||||
let (vsib, index_size) = if raw.IsVsib() != 0 {
|
let (vsib, index_size) = if raw.IsVsib() != 0 {
|
||||||
(
|
(
|
||||||
Some(Vsib {
|
Some(Vsib {
|
||||||
vsib_element_size: raw.Vsib.ElemSize,
|
vsib_element_size: unsafe { raw.__bindgen_anon_1.Vsib.ElemSize },
|
||||||
vsib_element_count: raw.Vsib.ElemCount,
|
vsib_element_count: unsafe { raw.__bindgen_anon_1.Vsib.ElemCount },
|
||||||
}),
|
}),
|
||||||
Some(raw.Vsib.IndexSize.into()),
|
Some(unsafe { raw.__bindgen_anon_1.Vsib.IndexSize.into() }),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(None, index_size)
|
(None, index_size)
|
||||||
@ -460,7 +461,9 @@ impl Default for OpInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OpInfo {
|
impl OpInfo {
|
||||||
/// Returns the associated [OpReg](OpReg) for register operands. Returns [`None`] otherwise.
|
/// Returns the associated [`OpReg`] for register operands. Returns [`None`] otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn as_reg(&self) -> Option<&OpReg> {
|
pub fn as_reg(&self) -> Option<&OpReg> {
|
||||||
if let OpInfo::Reg(o) = self {
|
if let OpInfo::Reg(o) = self {
|
||||||
Some(o)
|
Some(o)
|
||||||
@ -469,7 +472,9 @@ impl OpInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the associated [OpMem](OpMem) for memory operands. Returns [`None`] otherwise.
|
/// Returns the associated [`OpMem`] for memory operands. Returns [`None`] otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn as_mem(&self) -> Option<&OpMem> {
|
pub fn as_mem(&self) -> Option<&OpMem> {
|
||||||
if let OpInfo::Mem(o) = self {
|
if let OpInfo::Mem(o) = self {
|
||||||
Some(o)
|
Some(o)
|
||||||
@ -479,6 +484,8 @@ impl OpInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the associated immediate value for immediate operands. Returns [`None`] otherwise.
|
/// Returns the associated immediate value for immediate operands. Returns [`None`] otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn as_imm(&self) -> Option<u64> {
|
pub fn as_imm(&self) -> Option<u64> {
|
||||||
if let OpInfo::Imm(o) = self {
|
if let OpInfo::Imm(o) = self {
|
||||||
Some(*o)
|
Some(*o)
|
||||||
@ -487,7 +494,9 @@ impl OpInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the associated [OpAddr](OpAddr) for absolute address operands. Returns [`None`] otherwise.
|
/// Returns the associated [`OpAddr`] for absolute address operands. Returns [`None`] otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn as_addr(&self) -> Option<&OpAddr> {
|
pub fn as_addr(&self) -> Option<&OpAddr> {
|
||||||
if let OpInfo::Addr(o) = self {
|
if let OpInfo::Addr(o) = self {
|
||||||
Some(o)
|
Some(o)
|
||||||
@ -497,6 +506,8 @@ impl OpInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the associated constant value for constant operands. Returns [`None`] otherwise.
|
/// Returns the associated constant value for constant operands. Returns [`None`] otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn as_const(&self) -> Option<u64> {
|
pub fn as_const(&self) -> Option<u64> {
|
||||||
if let OpInfo::Const(o) = self {
|
if let OpInfo::Const(o) = self {
|
||||||
Some(*o)
|
Some(*o)
|
||||||
@ -506,6 +517,8 @@ impl OpInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Some` for bank operands. Returns [`None`] otherwise.
|
/// Returns `Some` for bank operands. Returns [`None`] otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn as_bank(&self) -> Option<()> {
|
pub fn as_bank(&self) -> Option<()> {
|
||||||
if let OpInfo::Bank = self {
|
if let OpInfo::Bank = self {
|
||||||
Some(())
|
Some(())
|
||||||
@ -515,31 +528,43 @@ impl OpInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` for register operands. Returns `false` otherwise.
|
/// Returns `true` for register operands. Returns `false` otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn is_reg(&self) -> bool {
|
pub fn is_reg(&self) -> bool {
|
||||||
self.as_reg().is_some()
|
self.as_reg().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` for memory operands. Returns `false` otherwise.
|
/// Returns `true` for memory operands. Returns `false` otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn is_mem(&self) -> bool {
|
pub fn is_mem(&self) -> bool {
|
||||||
self.as_mem().is_some()
|
self.as_mem().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` for immediate operands. Returns `false` otherwise.
|
/// Returns `true` for immediate operands. Returns `false` otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn is_imm(&self) -> bool {
|
pub fn is_imm(&self) -> bool {
|
||||||
self.as_imm().is_some()
|
self.as_imm().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` for absolute address operands. Returns `false` otherwise.
|
/// Returns `true` for absolute address operands. Returns `false` otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn is_addr(&self) -> bool {
|
pub fn is_addr(&self) -> bool {
|
||||||
self.as_addr().is_some()
|
self.as_addr().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` for constant operands. Returns `false` otherwise.
|
/// Returns `true` for constant operands. Returns `false` otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
self.as_const().is_some()
|
self.as_const().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` for bank operands. Returns `false` otherwise.
|
/// Returns `true` for bank operands. Returns `false` otherwise.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn is_bank(&self) -> bool {
|
pub fn is_bank(&self) -> bool {
|
||||||
self.as_bank().is_some()
|
self.as_bank().is_some()
|
||||||
}
|
}
|
||||||
@ -548,25 +573,26 @@ impl OpInfo {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl OpInfo {
|
impl OpInfo {
|
||||||
pub(crate) fn from_raw(raw: ffi::ND_OPERAND) -> Result<Self, DecodeError> {
|
pub(crate) fn from_raw(raw: ffi::ND_OPERAND) -> Result<Self, DecodeError> {
|
||||||
match raw.Type {
|
let typ = raw.Type() as i32;
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_NOT_PRESENT => Ok(OpInfo::None),
|
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_REG => {
|
if typ == ffi::_ND_OPERAND_TYPE::ND_OP_NOT_PRESENT as i32 {
|
||||||
|
Ok(OpInfo::None)
|
||||||
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_REG as i32 {
|
||||||
Ok(OpInfo::Reg(OpReg::from_raw(unsafe { raw.Info.Register })?))
|
Ok(OpInfo::Reg(OpReg::from_raw(unsafe { raw.Info.Register })?))
|
||||||
}
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_MEM as i32 {
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_MEM => {
|
|
||||||
Ok(OpInfo::Mem(OpMem::from_raw(unsafe { raw.Info.Memory })?))
|
Ok(OpInfo::Mem(OpMem::from_raw(unsafe { raw.Info.Memory })?))
|
||||||
}
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_IMM as i32 {
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_IMM => Ok(OpInfo::Imm(unsafe { raw.Info.Immediate }.Imm)),
|
Ok(OpInfo::Imm(unsafe { raw.Info.Immediate }.Imm))
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_OFFS => {
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_OFFS as i32 {
|
||||||
Ok(OpInfo::Offs(unsafe { raw.Info.RelativeOffset }.Rel))
|
Ok(OpInfo::Offs(unsafe { raw.Info.RelativeOffset }.Rel))
|
||||||
}
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_ADDR as i32 {
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_ADDR => {
|
|
||||||
Ok(OpInfo::Addr(OpAddr::from_raw(unsafe { raw.Info.Address })))
|
Ok(OpInfo::Addr(OpAddr::from_raw(unsafe { raw.Info.Address })))
|
||||||
}
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_CONST as i32 {
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_CONST => {
|
|
||||||
Ok(OpInfo::Const(unsafe { raw.Info.Constant }.Const))
|
Ok(OpInfo::Const(unsafe { raw.Info.Constant }.Const))
|
||||||
}
|
} else if typ == ffi::_ND_OPERAND_TYPE::ND_OP_BANK as i32 {
|
||||||
ffi::_ND_OPERAND_TYPE::ND_OP_BANK => Ok(OpInfo::Bank),
|
Ok(OpInfo::Bank)
|
||||||
|
} else {
|
||||||
|
Err(DecodeError::InternalError(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,7 +646,6 @@ impl fmt::Display for OpSize {
|
|||||||
impl OpSize {
|
impl OpSize {
|
||||||
pub(crate) fn from_raw(value: ffi::ND_OPERAND_SIZE) -> Result<Self, DecodeError> {
|
pub(crate) fn from_raw(value: ffi::ND_OPERAND_SIZE) -> Result<Self, DecodeError> {
|
||||||
match value {
|
match value {
|
||||||
0 => Ok(OpSize::Bytes(0)),
|
|
||||||
ffi::ND_SIZE_8BIT => Ok(OpSize::Bytes(1)),
|
ffi::ND_SIZE_8BIT => Ok(OpSize::Bytes(1)),
|
||||||
ffi::ND_SIZE_16BIT => Ok(OpSize::Bytes(2)),
|
ffi::ND_SIZE_16BIT => Ok(OpSize::Bytes(2)),
|
||||||
ffi::ND_SIZE_32BIT => Ok(OpSize::Bytes(4)),
|
ffi::ND_SIZE_32BIT => Ok(OpSize::Bytes(4)),
|
||||||
@ -645,6 +670,7 @@ impl OpSize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Operand access mode.
|
/// Operand access mode.
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
||||||
pub struct OpAccess {
|
pub struct OpAccess {
|
||||||
/// The operand is read.
|
/// The operand is read.
|
||||||
@ -701,32 +727,6 @@ pub struct Decorator {
|
|||||||
pub broadcast: Option<Broadcast>,
|
pub broadcast: Option<Broadcast>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl Decorator {
|
|
||||||
pub(crate) fn from_raw(raw: ffi::ND_OPERAND_DECORATOR) -> Decorator {
|
|
||||||
let mask_register = if raw.HasMask() != 0 {
|
|
||||||
Some(raw.Mask.Msk)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let broadcast = if raw.HasBroadcast() != 0 {
|
|
||||||
Some(Broadcast {
|
|
||||||
count: raw.Broadcast.Count,
|
|
||||||
size: raw.Broadcast.Size,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
mask_register,
|
|
||||||
has_zero: raw.HasZero() != 0,
|
|
||||||
broadcast,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes an instruction operand.
|
/// Describes an instruction operand.
|
||||||
///
|
///
|
||||||
/// Each operand type encodes different information. See [`OpInfo`] for details.
|
/// Each operand type encodes different information. See [`OpInfo`] for details.
|
||||||
@ -775,23 +775,11 @@ pub struct Operand {
|
|||||||
/// cases.
|
/// cases.
|
||||||
pub size: OpSize,
|
pub size: OpSize,
|
||||||
|
|
||||||
/// Raw size inside the instruction.
|
|
||||||
///
|
|
||||||
/// This will usually be identical to [size](Operand::size), however, some instructions force the actual size of
|
|
||||||
/// their operands to 64 bit (`PUSH`/`POP` or branches are good examples).
|
|
||||||
///
|
|
||||||
/// Although the raw size of the relative offset or the immediate will be [raw_size](Operand::raw_size), internally,
|
|
||||||
/// the CPU will use [size](Operand::size) (usually sign-extended).
|
|
||||||
pub raw_size: OpSize,
|
|
||||||
|
|
||||||
/// Access mode.
|
/// Access mode.
|
||||||
pub access: OpAccess,
|
pub access: OpAccess,
|
||||||
|
|
||||||
/// `true` if the operand is default. This also applies to implicit operands.
|
/// `true` if the operand is default. This also applies to implicit operands.
|
||||||
pub is_default: bool,
|
pub is_default: bool,
|
||||||
|
|
||||||
/// Decorator information.
|
|
||||||
pub decorator: Decorator,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -800,10 +788,8 @@ impl Operand {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
info: OpInfo::from_raw(raw)?,
|
info: OpInfo::from_raw(raw)?,
|
||||||
size: OpSize::from_raw(raw.Size)?,
|
size: OpSize::from_raw(raw.Size)?,
|
||||||
raw_size: OpSize::from_raw(raw.RawSize)?,
|
|
||||||
access: OpAccess::from_raw(raw.Access),
|
access: OpAccess::from_raw(raw.Access),
|
||||||
is_default: unsafe { raw.Flags.__bindgen_anon_1 }.IsDefault() != 0,
|
is_default: unsafe { raw.Flags.__bindgen_anon_1 }.IsDefault() != 0,
|
||||||
decorator: Decorator::from_raw(raw.Decorator),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -932,6 +918,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn dest(&self, index: usize) -> Option<Operand> {
|
pub fn dest(&self, index: usize) -> Option<Operand> {
|
||||||
let op = match index {
|
let op = match index {
|
||||||
0 => unsafe { self.op_rlut.Dst1.as_ref() },
|
0 => unsafe { self.op_rlut.Dst1.as_ref() },
|
||||||
@ -961,6 +948,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn src(&self, index: usize) -> Option<Operand> {
|
pub fn src(&self, index: usize) -> Option<Operand> {
|
||||||
let op = match index {
|
let op = match index {
|
||||||
0 => unsafe { self.op_rlut.Src1.as_ref() },
|
0 => unsafe { self.op_rlut.Src1.as_ref() },
|
||||||
@ -991,6 +979,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn mem(&self, index: usize) -> Option<Operand> {
|
pub fn mem(&self, index: usize) -> Option<Operand> {
|
||||||
let op = match index {
|
let op = match index {
|
||||||
0 => unsafe { self.op_rlut.Mem1.as_ref() },
|
0 => unsafe { self.op_rlut.Mem1.as_ref() },
|
||||||
@ -1013,6 +1002,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn stack(&self) -> Option<Operand> {
|
pub fn stack(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Stack.as_ref() };
|
let op = unsafe { self.op_rlut.Stack.as_ref() };
|
||||||
|
|
||||||
@ -1031,6 +1021,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn flags(&self) -> Option<Operand> {
|
pub fn flags(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Flags.as_ref() };
|
let op = unsafe { self.op_rlut.Flags.as_ref() };
|
||||||
|
|
||||||
@ -1049,6 +1040,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rip(&self) -> Option<Operand> {
|
pub fn rip(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rip.as_ref() };
|
let op = unsafe { self.op_rlut.Rip.as_ref() };
|
||||||
|
|
||||||
@ -1067,6 +1059,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn cs(&self) -> Option<Operand> {
|
pub fn cs(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Cs.as_ref() };
|
let op = unsafe { self.op_rlut.Cs.as_ref() };
|
||||||
|
|
||||||
@ -1085,6 +1078,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn ss(&self) -> Option<Operand> {
|
pub fn ss(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Ss.as_ref() };
|
let op = unsafe { self.op_rlut.Ss.as_ref() };
|
||||||
|
|
||||||
@ -1103,6 +1097,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rax(&self) -> Option<Operand> {
|
pub fn rax(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rax.as_ref() };
|
let op = unsafe { self.op_rlut.Rax.as_ref() };
|
||||||
|
|
||||||
@ -1121,6 +1116,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rcx(&self) -> Option<Operand> {
|
pub fn rcx(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rcx.as_ref() };
|
let op = unsafe { self.op_rlut.Rcx.as_ref() };
|
||||||
|
|
||||||
@ -1139,6 +1135,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rdx(&self) -> Option<Operand> {
|
pub fn rdx(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rdx.as_ref() };
|
let op = unsafe { self.op_rlut.Rdx.as_ref() };
|
||||||
|
|
||||||
@ -1157,6 +1154,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rbx(&self) -> Option<Operand> {
|
pub fn rbx(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rbx.as_ref() };
|
let op = unsafe { self.op_rlut.Rbx.as_ref() };
|
||||||
|
|
||||||
@ -1175,6 +1173,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rsp(&self) -> Option<Operand> {
|
pub fn rsp(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rsp.as_ref() };
|
let op = unsafe { self.op_rlut.Rsp.as_ref() };
|
||||||
|
|
||||||
@ -1193,6 +1192,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rbp(&self) -> Option<Operand> {
|
pub fn rbp(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rbp.as_ref() };
|
let op = unsafe { self.op_rlut.Rbp.as_ref() };
|
||||||
|
|
||||||
@ -1211,6 +1211,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rsi(&self) -> Option<Operand> {
|
pub fn rsi(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rsi.as_ref() };
|
let op = unsafe { self.op_rlut.Rsi.as_ref() };
|
||||||
|
|
||||||
@ -1229,6 +1230,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
/// This function will panic if the result of the C library is unrecognized. This can not happen under normal
|
||||||
/// circumstances.
|
/// circumstances.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
pub fn rdi(&self) -> Option<Operand> {
|
pub fn rdi(&self) -> Option<Operand> {
|
||||||
let op = unsafe { self.op_rlut.Rdi.as_ref() };
|
let op = unsafe { self.op_rlut.Rdi.as_ref() };
|
||||||
|
|
||||||
@ -1236,7 +1238,7 @@ impl<'a> OperandsLookup<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of [Operand](Operand)s.
|
/// A collection of [`Operand`]s.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
||||||
pub struct Operands {
|
pub struct Operands {
|
||||||
pub(crate) operands: [Operand; 10],
|
pub(crate) operands: [Operand; 10],
|
||||||
@ -1266,7 +1268,6 @@ mod tests {
|
|||||||
|
|
||||||
let dest = operands[0];
|
let dest = operands[0];
|
||||||
assert_eq!(dest.size, OpSize::Bytes(1));
|
assert_eq!(dest.size, OpSize::Bytes(1));
|
||||||
assert_eq!(dest.raw_size, OpSize::Bytes(1));
|
|
||||||
assert_eq!(dest.is_default, false);
|
assert_eq!(dest.is_default, false);
|
||||||
assert!(dest.access.write);
|
assert!(dest.access.write);
|
||||||
|
|
||||||
@ -1281,7 +1282,6 @@ mod tests {
|
|||||||
|
|
||||||
let src = operands[1];
|
let src = operands[1];
|
||||||
assert_eq!(src.size, OpSize::Bytes(1));
|
assert_eq!(src.size, OpSize::Bytes(1));
|
||||||
assert_eq!(src.raw_size, OpSize::Bytes(1));
|
|
||||||
assert_eq!(src.is_default, false);
|
assert_eq!(src.is_default, false);
|
||||||
assert!(src.access.read);
|
assert!(src.access.read);
|
||||||
|
|
||||||
|
198
bindings/rsbddisasm/update_ins.py
Normal file
198
bindings/rsbddisasm/update_ins.py
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from git import Repo
|
||||||
|
|
||||||
|
repo = Repo(search_parent_directories=True)
|
||||||
|
root = Path(repo.working_tree_dir)
|
||||||
|
|
||||||
|
print(f"Repo root: {root}")
|
||||||
|
|
||||||
|
hdr_dirs = root / "inc"
|
||||||
|
x86_constants = hdr_dirs / "bdx86_constants.h"
|
||||||
|
|
||||||
|
print(f"Looking for enums in {x86_constants}")
|
||||||
|
|
||||||
|
with open(x86_constants, "r") as data:
|
||||||
|
nd_ins = []
|
||||||
|
nd_ins_set = []
|
||||||
|
nd_ins_type = []
|
||||||
|
|
||||||
|
for line in data:
|
||||||
|
if "INVALID" in line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(" ND_CAT_"):
|
||||||
|
token = line.replace(',', '').strip()
|
||||||
|
nd_ins_type.append(token)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(" ND_SET_"):
|
||||||
|
token = line.replace(',', '').strip()
|
||||||
|
nd_ins_set.append(token)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(" ND_INS_"):
|
||||||
|
token = line.replace(',', '').strip()
|
||||||
|
nd_ins.append(token)
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"ND_INS_: {len(nd_ins)} ND_SET_: {len(nd_ins_set)} ND_CAT_: {len(nd_ins_type)}")
|
||||||
|
|
||||||
|
bindings = root / "bindings/rsbddisasm/bddisasm/src"
|
||||||
|
mnemonic = bindings / "mnemonic.rs"
|
||||||
|
ins_cat = bindings / "instruction_category.rs"
|
||||||
|
isa_set = bindings / "isa_set.rs"
|
||||||
|
|
||||||
|
license_header = """
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Bitdefender
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(f"Generating {mnemonic}")
|
||||||
|
|
||||||
|
with open(mnemonic, "w") as fmnemonic:
|
||||||
|
fmnemonic.write(license_header)
|
||||||
|
fmnemonic.write("//! Mnemonics.\n")
|
||||||
|
fmnemonic.write("\n")
|
||||||
|
fmnemonic.write("use super::decode_error::DecodeError;\n")
|
||||||
|
fmnemonic.write("use core::convert::TryFrom;\n")
|
||||||
|
|
||||||
|
mnemonic_enum_def = """
|
||||||
|
/// Uniquely identifies an instruction.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum Mnemonic {
|
||||||
|
"""
|
||||||
|
fmnemonic.write(mnemonic_enum_def)
|
||||||
|
for ins in nd_ins:
|
||||||
|
line = ins.replace("ND_INS_", "")
|
||||||
|
fmnemonic.write(f"{line},\n")
|
||||||
|
|
||||||
|
fmnemonic.write("}\n")
|
||||||
|
|
||||||
|
try_from = """
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
||||||
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
|
fn try_from(value: ffi::ND_INS_CLASS) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
ffi::_ND_INS_CLASS::ND_INS_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||||
|
"""
|
||||||
|
fmnemonic.write(try_from)
|
||||||
|
for ins in nd_ins:
|
||||||
|
line = f"ffi::_ND_INS_CLASS::{ins} => Ok(Mnemonic::{ins.replace('ND_INS_', '')}),\n"
|
||||||
|
fmnemonic.write(line)
|
||||||
|
|
||||||
|
end = """
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
fmnemonic.write(end)
|
||||||
|
|
||||||
|
print(f"Generating {ins_cat}")
|
||||||
|
|
||||||
|
with open(ins_cat, "w") as finscat:
|
||||||
|
finscat.write(license_header)
|
||||||
|
finscat.write("//! Instruction categories.\n")
|
||||||
|
finscat.write("\n")
|
||||||
|
finscat.write("use super::decode_error::DecodeError;\n")
|
||||||
|
finscat.write("use core::convert::TryFrom;\n")
|
||||||
|
|
||||||
|
ins_cat_enum_def = """
|
||||||
|
/// Instruction category.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum Category {
|
||||||
|
"""
|
||||||
|
finscat.write(ins_cat_enum_def)
|
||||||
|
for ins in nd_ins_type:
|
||||||
|
line = ins.replace("ND_CAT_", "")
|
||||||
|
if line[0].isdigit():
|
||||||
|
line = f"I{line}"
|
||||||
|
finscat.write(f"{line},\n")
|
||||||
|
|
||||||
|
finscat.write("}\n")
|
||||||
|
|
||||||
|
try_from = """
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
||||||
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
|
fn try_from(value: ffi::ND_INS_CATEGORY) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
ffi::_ND_INS_TYPE::ND_CAT_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||||
|
"""
|
||||||
|
finscat.write(try_from)
|
||||||
|
for ins in nd_ins_type:
|
||||||
|
ok = ins.replace('ND_CAT_', '')
|
||||||
|
if ok[0].isdigit():
|
||||||
|
ok = f"I{ok}"
|
||||||
|
line = f"ffi::_ND_INS_TYPE::{ins} => Ok(Category::{ok}),\n"
|
||||||
|
finscat.write(line)
|
||||||
|
|
||||||
|
end = """
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
finscat.write(end)
|
||||||
|
|
||||||
|
print(f"Generating {isa_set}")
|
||||||
|
|
||||||
|
with open(isa_set, "w") as fset:
|
||||||
|
fset.write(license_header)
|
||||||
|
fset.write("//! Instruction sets.\n")
|
||||||
|
fset.write("\n")
|
||||||
|
fset.write("use super::decode_error::DecodeError;\n")
|
||||||
|
fset.write("use core::convert::TryFrom;\n")
|
||||||
|
|
||||||
|
ins_set_enum_def = """
|
||||||
|
/// ISA set.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum IsaSet {
|
||||||
|
"""
|
||||||
|
fset.write(ins_set_enum_def)
|
||||||
|
for ins in nd_ins_set:
|
||||||
|
line = ins.replace("ND_SET_", "")
|
||||||
|
if line[0].isdigit():
|
||||||
|
line = f"I{line}"
|
||||||
|
fset.write(f"{line},\n")
|
||||||
|
|
||||||
|
fset.write("}\n")
|
||||||
|
|
||||||
|
try_from = """
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
||||||
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
|
fn try_from(value: ffi::ND_INS_SET) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
ffi::_ND_INS_SET::ND_SET_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||||
|
"""
|
||||||
|
fset.write(try_from)
|
||||||
|
for ins in nd_ins_set:
|
||||||
|
ok = ins.replace('ND_SET_', '')
|
||||||
|
if ok[0].isdigit():
|
||||||
|
ok = f"I{ok}"
|
||||||
|
line = f"ffi::_ND_INS_SET::{ins} => Ok(IsaSet::{ok}),\n"
|
||||||
|
fset.write(line)
|
||||||
|
|
||||||
|
end = """
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
fset.write(end)
|
||||||
|
|
||||||
|
subprocess.check_output(["cargo", "fmt"])
|
@ -50,9 +50,7 @@ else ()
|
|||||||
-Wno-unused-function
|
-Wno-unused-function
|
||||||
-Wno-multichar
|
-Wno-multichar
|
||||||
-Wno-incompatible-pointer-types
|
-Wno-incompatible-pointer-types
|
||||||
-Wno-discarded-qualifiers
|
|
||||||
-Wnull-dereference
|
-Wnull-dereference
|
||||||
-Wduplicated-cond
|
|
||||||
-Werror=implicit-function-declaration
|
-Werror=implicit-function-declaration
|
||||||
-pipe
|
-pipe
|
||||||
-fwrapv
|
-fwrapv
|
||||||
@ -65,4 +63,10 @@ else ()
|
|||||||
-gdwarf-4
|
-gdwarf-4
|
||||||
-grecord-gcc-switches
|
-grecord-gcc-switches
|
||||||
-march=westmere)
|
-march=westmere)
|
||||||
|
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||||
|
target_compile_options(
|
||||||
|
disasmtool
|
||||||
|
PRIVATE -Wno-discarded-qualifiers
|
||||||
|
-Wduplicated-cond)
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,24 @@
|
|||||||
#ifndef DISASMTOOL_H
|
#ifndef DISASMTOOL_H
|
||||||
#define DISASMTOOL_H
|
#define DISASMTOOL_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#define _In_
|
||||||
|
#define _Inout_
|
||||||
|
#define _Out_
|
||||||
|
#define _Success_(x)
|
||||||
|
|
||||||
|
typedef char CHAR, *PCHAR;
|
||||||
|
typedef unsigned char BYTE, *PBYTE;
|
||||||
|
|
||||||
|
typedef int32_t INT32;
|
||||||
|
typedef uint32_t DWORD;
|
||||||
|
|
||||||
|
#define UNREFERENCED_PARAMETER(P) (void)(P)
|
||||||
|
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||||
|
#endif // !WIN32
|
||||||
|
|
||||||
typedef enum _DISASM_COMMAND
|
typedef enum _DISASM_COMMAND
|
||||||
{
|
{
|
||||||
@ -29,26 +47,24 @@ typedef struct _DISASM_OPTIONS
|
|||||||
size_t Size; // Buffer size.
|
size_t Size; // Buffer size.
|
||||||
size_t Offset; // Offset inside the buffer.
|
size_t Offset; // Offset inside the buffer.
|
||||||
size_t Rip; // Virtual RIP.
|
size_t Rip; // Virtual RIP.
|
||||||
BOOLEAN Highlight; // Highlight instruction components, if true.
|
bool Highlight; // Highlight instruction components, if true.
|
||||||
BOOLEAN ExtendedInfo; // Display extended instruction info, if true.
|
bool ExtendedInfo; // Display extended instruction info, if true.
|
||||||
BOOLEAN BitFields; // Display the various bitfields inside the instruction, if true.
|
bool BitFields; // Display the various bitfields inside the instruction, if true.
|
||||||
BOOLEAN Skip16; // Automatically jump over 16 bytes after each instruction.
|
bool Skip16; // Automatically jump over 16 bytes after each instruction.
|
||||||
BOOLEAN Stats; // Display disassembly stats (clocks / instruction, instructions / second), if true.
|
bool Skip1; // Automatically jump over one single byte after each instruction.
|
||||||
BOOLEAN Print; // Print instruction disassembly, if true.
|
bool Stats; // Display disassembly stats (clocks / instruction, instructions / second), if true.
|
||||||
|
bool Print; // Print instruction disassembly, if true.
|
||||||
uint8_t Mode; // Mode - 16, 32 or 64-bit mode.
|
uint8_t Mode; // Mode - 16, 32 or 64-bit mode.
|
||||||
uint8_t Ring; // Ring - 0, 1, 2 or 3.
|
uint8_t Ring; // Ring - 0, 1, 2 or 3.
|
||||||
uint8_t Vendor; // Preffered vendor.
|
uint8_t Vendor; // Preffered vendor.
|
||||||
uint8_t Feature; // Used features.
|
uint8_t Feature; // Used features.
|
||||||
char *FileName; // Input file, if any.
|
char *FileName; // Input file, if any.
|
||||||
size_t ShemuRegs[ND_MAX_GPR_REGS];
|
size_t ShemuRegs[ND_MAX_GPR_REGS];
|
||||||
BOOLEAN UseShemuRegs; // If truue, the registers in ShemuRegs will be used for shemu input.
|
bool UseShemuRegs; // If truue, the registers in ShemuRegs will be used for shemu input.
|
||||||
BOOLEAN BypassSelfWrites; // If true, shemu emulation will ignore self-modifications made by the shellcode.
|
bool BypassSelfWrites; // If true, shemu emulation will ignore self-modifications made by the shellcode.
|
||||||
|
|
||||||
// Internal.
|
// Internal.
|
||||||
INPUT_MODE InputMode;
|
INPUT_MODE InputMode;
|
||||||
HANDLE HandleFile;
|
|
||||||
HANDLE HandleMapping;
|
|
||||||
|
|
||||||
} DISASM_OPTIONS, *PDISASM_OPTIONS;
|
} DISASM_OPTIONS, *PDISASM_OPTIONS;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
|
|
||||||
project(disasmtool LANGUAGES CXX)
|
|
||||||
|
|
||||||
# Use Release as the build type if no build type was specified and we're not using a multi-config generator .
|
|
||||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
||||||
message(STATUS "No build type given. Will use 'Release'")
|
|
||||||
set(CMAKE_BUILD_TYPE
|
|
||||||
"Release"
|
|
||||||
CACHE STRING "Choose the type of build." FORCE)
|
|
||||||
# Set the possible values of build type for cmake-gui.
|
|
||||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_executable(disasmtool disasmtool.cpp dumpers.cpp rapidjson.cpp)
|
|
||||||
|
|
||||||
target_compile_options(
|
|
||||||
disasmtool
|
|
||||||
PRIVATE "$<$<CONFIG:Release>:-U_FORTIFY_SOURCE>"
|
|
||||||
"$<$<CONFIG:Release>:-D_FORTIFY_SOURCE=2>"
|
|
||||||
-Wall
|
|
||||||
-Wextra
|
|
||||||
-Wshadow
|
|
||||||
-Wformat-security
|
|
||||||
-Wstrict-overflow=2
|
|
||||||
-Wno-unused-function
|
|
||||||
-Wno-multichar
|
|
||||||
-Werror=format-security
|
|
||||||
-pipe
|
|
||||||
-fpie
|
|
||||||
-fwrapv
|
|
||||||
-fno-strict-aliasing
|
|
||||||
-fstack-protector-strong
|
|
||||||
-ffunction-sections
|
|
||||||
-fdata-sections
|
|
||||||
-g3
|
|
||||||
-gdwarf-4
|
|
||||||
-grecord-gcc-switches
|
|
||||||
-march=nehalem
|
|
||||||
-fno-omit-frame-pointer)
|
|
||||||
|
|
||||||
if (NOT TARGET bddisasm)
|
|
||||||
find_package(bddisasm REQUIRED)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
find_package(RapidJSON QUIET REQUIRED)
|
|
||||||
|
|
||||||
target_link_libraries(disasmtool PRIVATE bddisasm::bddisasm bddisasm::bdshemu)
|
|
||||||
# :( https://github.com/satishbabariya/modern-cmake#good-boys-export-their-targets
|
|
||||||
target_include_directories(disasmtool PRIVATE ${RapidJSON_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
|
||||||
include(CheckIPOSupported)
|
|
||||||
check_ipo_supported(RESULT USE_IPO)
|
|
||||||
if (USE_IPO)
|
|
||||||
set_target_properties(disasmtool PROPERTIES INTERPROCEDURAL_OPTIMIZATION True)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set_target_properties(
|
|
||||||
disasmtool
|
|
||||||
PROPERTIES POSITION_INDEPENDENT_CODE ON
|
|
||||||
CXX_STANDARD 17
|
|
||||||
CXX_STANDARD_REQUIRED ON
|
|
||||||
CXX_EXTENSIONS ON)
|
|
@ -1,39 +0,0 @@
|
|||||||
.PHONY: all last_build debug release
|
|
||||||
|
|
||||||
CMAKE_BUILD_DIR = build
|
|
||||||
|
|
||||||
CPUCOUNT := $(shell grep -c "^processor" /proc/cpuinfo)
|
|
||||||
|
|
||||||
ifneq (,$(CPUCOUNT))
|
|
||||||
EXTRA_MAKE_ARGS := -j$(CPUCOUNT)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# NINJA := $(shell which ninja 2>/dev/null)
|
|
||||||
|
|
||||||
ifneq (,$(NINJA))
|
|
||||||
GENERATOR := "Ninja"
|
|
||||||
else
|
|
||||||
GENERATOR := "Unix Makefiles"
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(shell if [ ! -d $(CMAKE_BUILD_DIR) ]; then mkdir $(CMAKE_BUILD_DIR); fi)
|
|
||||||
|
|
||||||
all: last_build
|
|
||||||
|
|
||||||
last_build:
|
|
||||||
@cmake -H. -G$(GENERATOR) -B$(CMAKE_BUILD_DIR) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
||||||
@cmake --build $(CMAKE_BUILD_DIR) -- $(EXTRA_MAKE_ARGS)
|
|
||||||
|
|
||||||
debug: CMAKE_BUILD_TYPE := Debug
|
|
||||||
debug: build
|
|
||||||
|
|
||||||
release: CMAKE_BUILD_TYPE := Release
|
|
||||||
release: build
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@if [ -d $(CMAKE_BUILD_DIR) ]; then cmake --build $(CMAKE_BUILD_DIR) --target clean; fi
|
|
||||||
|
|
||||||
reset:
|
|
||||||
@if [ -d $(CMAKE_BUILD_DIR) ]; then rm -r $(CMAKE_BUILD_DIR); fi
|
|
||||||
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Bitdefender
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <rapidjson/stringbuffer.h>
|
|
||||||
using StringBuffer = rapidjson::StringBuffer;
|
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
|
|
||||||
// On windows, simply include Windows.h
|
|
||||||
#ifndef _WIN32
|
|
||||||
typedef void VOID, *PVOID;
|
|
||||||
typedef unsigned char BOOLEAN, *PBOOLEAN;
|
|
||||||
typedef char CHAR, *PCHAR;
|
|
||||||
typedef unsigned char BYTE, *PBYTE;
|
|
||||||
typedef unsigned short WORD, *PWORD;
|
|
||||||
typedef unsigned int DWORD, *PDWORD;
|
|
||||||
typedef unsigned long long QWORD, *PQWORD;
|
|
||||||
typedef size_t SIZE_T;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX_PATH
|
|
||||||
#define MAX_PATH 255
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Main disasm header file.
|
|
||||||
#include "bdshemu.h"
|
|
||||||
#include "bddisasm.h"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
std::string enc_mode_to_str(const uint8_t enc_mode);
|
|
||||||
std::string op_type_to_str(const ND_OPERAND_TYPE type);
|
|
||||||
std::string op_enc_to_str(const ND_OPERAND_ENCODING Encoding);
|
|
||||||
std::string ins_class_to_str(const ND_INS_CLASS cls);
|
|
||||||
std::string ins_cat_to_str(ND_INS_CATEGORY category);
|
|
||||||
std::string ins_set_to_str(ND_INS_SET ins_set);
|
|
||||||
std::string reg_to_str(const int reg, const ND_REG_TYPE type);
|
|
||||||
std::string reg_type_to_str(const ND_REG_TYPE type);
|
|
||||||
|
|
||||||
StringBuffer instrux_to_json(INSTRUX *instrux, size_t rip, bool text_only = false);
|
|
||||||
StringBuffer byte_to_json(uint8_t byte, size_t rip);
|
|
||||||
StringBuffer disassemble_one(uint8_t *bytes, size_t size, size_t rip, uint8_t bits, uint8_t vendor = ND_VEND_INTEL);
|
|
||||||
|
|
||||||
bool regs_from_json(const std::string &str, SHEMU_GPR_REGS ®s, bool &update_rsp);
|
|
@ -1,927 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Bitdefender
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <memory>
|
|
||||||
#include <limits>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cpuid.h>
|
|
||||||
|
|
||||||
#include "external/argparse.h"
|
|
||||||
|
|
||||||
#include "disasm.hpp"
|
|
||||||
|
|
||||||
#define STACK_SIZE 0x2000
|
|
||||||
#define PAGE_MASK 0xFFFFFFFFFFFFF000
|
|
||||||
|
|
||||||
static const long NSEC_PER_SEC = (1000ULL * 1000ULL * 1000ULL);
|
|
||||||
|
|
||||||
static const char *gSpaces[16] =
|
|
||||||
{
|
|
||||||
"",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct options {
|
|
||||||
size_t rip;
|
|
||||||
size_t offset;
|
|
||||||
size_t size;
|
|
||||||
size_t count;
|
|
||||||
|
|
||||||
uint8_t bits;
|
|
||||||
|
|
||||||
uint8_t vendor;
|
|
||||||
bool no_color;
|
|
||||||
bool verbose;
|
|
||||||
bool dump_stats;
|
|
||||||
bool interactive;
|
|
||||||
bool comm;
|
|
||||||
bool json_output;
|
|
||||||
bool extended;
|
|
||||||
|
|
||||||
bool shemu;
|
|
||||||
std::string shctx;
|
|
||||||
bool kernel;
|
|
||||||
|
|
||||||
std::string in_file;
|
|
||||||
std::string hex_string;
|
|
||||||
std::string hex_file;
|
|
||||||
std::string shctx_file;
|
|
||||||
std::string shdec_file;
|
|
||||||
|
|
||||||
// From here on, these are set internally
|
|
||||||
std::unique_ptr<uint8_t[]> bytes;
|
|
||||||
size_t actual_size;
|
|
||||||
int address_size;
|
|
||||||
|
|
||||||
bool output_redirected;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#if !defined(BDDISASM_HAS_VSNPRINTF)
|
|
||||||
int nd_vsnprintf_s(char *buffer, size_t sizeOfBuffer, [[maybe_unused]] size_t count, const char *format, va_list argptr)
|
|
||||||
{
|
|
||||||
return vsnprintf(buffer, sizeOfBuffer, format, argptr);
|
|
||||||
}
|
|
||||||
#endif // !defined(BDDISASM_HAS_VSNPRINTF)
|
|
||||||
|
|
||||||
#if !defined(BDDISASM_HAS_MEMSET)
|
|
||||||
void *
|
|
||||||
nd_memset(void *s, int c, size_t n)
|
|
||||||
{
|
|
||||||
return memset(s, c, n);
|
|
||||||
}
|
|
||||||
#endif // !defined(BDDISASM_HAS_MEMSET)
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _hexstring_to_bytes(options &opts)
|
|
||||||
{
|
|
||||||
if (!opts.hex_file.empty()) {
|
|
||||||
auto f = std::ifstream(opts.hex_file, std::ios::in);
|
|
||||||
|
|
||||||
if (!f.is_open()) {
|
|
||||||
std::cerr << "Failed to open file " << opts.hex_file << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
f.seekg(0, std::ios::end);
|
|
||||||
opts.hex_string.reserve(f.tellg());
|
|
||||||
f.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
opts.hex_string.assign((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.hex_string.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
opts.actual_size = 0;
|
|
||||||
opts.hex_string.erase(std::remove_if(opts.hex_string.begin(), opts.hex_string.end(), isspace), opts.hex_string.end());
|
|
||||||
|
|
||||||
// This is the maximum size, not the actual size
|
|
||||||
auto initial_size = opts.hex_string.length() / 2 + 1;
|
|
||||||
|
|
||||||
opts.bytes = std::make_unique<uint8_t[]>(initial_size);
|
|
||||||
auto bytes = opts.bytes.get();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < opts.hex_string.length(); i += 2) {
|
|
||||||
auto pair = opts.hex_string.substr(i, 2);
|
|
||||||
char *end_ptr;
|
|
||||||
|
|
||||||
if (pair == "0x" || pair == "0X" || pair == "\\x")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto b = static_cast<uint8_t>(std::strtoul(pair.c_str(), &end_ptr, 16));
|
|
||||||
|
|
||||||
size_t conv_size = static_cast<size_t>(end_ptr - pair.c_str());
|
|
||||||
|
|
||||||
if (conv_size != pair.length()) {
|
|
||||||
std::cerr << "Trying to convert invalid hex number: " << pair << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes[opts.actual_size++] = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _load_shctx(options &opts)
|
|
||||||
{
|
|
||||||
if (opts.shctx_file.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto f = std::ifstream(opts.shctx_file, std::ios::in);
|
|
||||||
if (!f.is_open()) {
|
|
||||||
std::cout << "Failed to open file " << opts.shctx_file << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
f.seekg(0, std::ios::end);
|
|
||||||
opts.shctx.reserve(f.tellg());
|
|
||||||
f.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
opts.shctx.assign((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _file_to_bytes(options &opts)
|
|
||||||
{
|
|
||||||
auto f = std::ifstream(opts.in_file, std::ios::in | std::ios::binary);
|
|
||||||
|
|
||||||
if (!f.is_open()) {
|
|
||||||
std::cerr << "Failed to open file " << opts.in_file << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
f.seekg(0, std::ios::end);
|
|
||||||
|
|
||||||
opts.actual_size = f.tellg();
|
|
||||||
|
|
||||||
if (opts.offset >= opts.actual_size) {
|
|
||||||
std::cerr << "Offset bigger than file size" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
f.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
opts.bytes = std::make_unique<uint8_t[]>(opts.actual_size);
|
|
||||||
|
|
||||||
f.read(reinterpret_cast<char*>(opts.bytes.get()), opts.actual_size);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't change the order (on linux these values are color codes)
|
|
||||||
enum Colors {
|
|
||||||
Reset = 0,
|
|
||||||
#if defined(_WIN32)
|
|
||||||
Red = FOREGROUND_INTENSITY | FOREGROUND_RED,
|
|
||||||
Green = FOREGROUND_INTENSITY | FOREGROUND_GREEN,
|
|
||||||
Yellow = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
|
|
||||||
Blue = FOREGROUND_INTENSITY | FOREGROUND_BLUE,
|
|
||||||
Magenta = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED,
|
|
||||||
Cyan = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN,
|
|
||||||
White = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
|
|
||||||
#elif defined(__unix__)
|
|
||||||
Red,
|
|
||||||
Green,
|
|
||||||
Yellow,
|
|
||||||
Blue,
|
|
||||||
Magenta,
|
|
||||||
Cyan,
|
|
||||||
White,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void _set_text_color(Colors color)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
static WORD old_attrs = -1;
|
|
||||||
|
|
||||||
if (old_attrs == -1) {
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO buffer_info;
|
|
||||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info);
|
|
||||||
old_attrs = buffer_info.wAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color == Reset)
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), old_attrs);
|
|
||||||
else
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
|
|
||||||
#elif defined(__unix__)
|
|
||||||
if (color == Reset)
|
|
||||||
std::cout << "\033[m";
|
|
||||||
else
|
|
||||||
std::cout << "\033[0;3" << color << "m";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct timespec diff_time(struct timespec const &end, struct timespec const &start)
|
|
||||||
{
|
|
||||||
struct timespec result;
|
|
||||||
|
|
||||||
if (end.tv_nsec > start.tv_nsec) {
|
|
||||||
result.tv_sec = end.tv_sec - start.tv_sec;
|
|
||||||
result.tv_nsec = end.tv_nsec - start.tv_nsec;
|
|
||||||
} else {
|
|
||||||
result.tv_sec = end.tv_sec - start.tv_sec - 1;
|
|
||||||
result.tv_nsec = NSEC_PER_SEC + end.tv_nsec - start.tv_nsec;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void print_instruction(const size_t rip, INSTRUX *instrux, const options &opts)
|
|
||||||
{
|
|
||||||
char instruxText[ND_MIN_BUF_SIZE];
|
|
||||||
uint32_t k = 0;
|
|
||||||
|
|
||||||
printf("%*zx ", opts.address_size, rip);
|
|
||||||
|
|
||||||
if (!opts.no_color)
|
|
||||||
{
|
|
||||||
_set_text_color(Magenta);
|
|
||||||
for (uint32_t idx = 0; idx < instrux->PrefLength; idx++, k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_set_text_color(Green);
|
|
||||||
for (uint32_t idx = 0; idx < (DWORD)(ND_IS_3DNOW(instrux) ? instrux->OpLength - 1 : instrux->OpLength); idx++, k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_set_text_color(Yellow);
|
|
||||||
for (uint32_t idx = 0; idx < (DWORD)(instrux->HasModRm + instrux->HasSib); idx++, k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_set_text_color(Blue);
|
|
||||||
for (uint32_t idx = 0; idx < (DWORD)(instrux->DispLength); idx++, k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_set_text_color(Red);
|
|
||||||
for (uint32_t idx = 0; idx < (DWORD)(instrux->Imm1Length + instrux->Imm2Length +
|
|
||||||
instrux->RelOffsLength + instrux->MoffsetLength +
|
|
||||||
instrux->HasSseImm + instrux->AddrLength); idx++, k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ND_IS_3DNOW(instrux))
|
|
||||||
{
|
|
||||||
_set_text_color(Green);
|
|
||||||
for (; k < instrux->Length; k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_set_text_color(Reset);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; k < instrux->Length; k++)
|
|
||||||
{
|
|
||||||
printf("%02x", instrux->InstructionBytes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << gSpaces[16 - instrux->Length];
|
|
||||||
|
|
||||||
NdToText(instrux, rip, sizeof(instruxText), instruxText);
|
|
||||||
|
|
||||||
std::cout << instruxText << std::endl;
|
|
||||||
|
|
||||||
if (opts.extended) {
|
|
||||||
const uint8_t opsize[3] = { 2, 4, 8 };
|
|
||||||
const uint8_t adsize[3] = { 2, 4, 8 };
|
|
||||||
const uint8_t veclen[3] = { 16, 32, 64 };
|
|
||||||
|
|
||||||
printf(" DSIZE: %2d, ASIZE: %2d, VLEN: ",
|
|
||||||
opsize[instrux->EfOpMode] * 8, adsize[instrux->AddrMode] * 8);
|
|
||||||
|
|
||||||
if (ND_HAS_VECTOR(instrux)) {
|
|
||||||
printf("%2d\n", veclen[instrux->VecMode] * 8);
|
|
||||||
} else {
|
|
||||||
printf("-\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(" ISA Set: %s, Ins cat: %s, Ins class: %d, CET tracked: %s\n",
|
|
||||||
ins_set_to_str(instrux->IsaSet).c_str(), ins_cat_to_str(instrux->Category).c_str(), instrux->Instruction,
|
|
||||||
instrux->IsCetTracked ? "yes" : "no");
|
|
||||||
|
|
||||||
if (0 != instrux->CpuidFlag.Flag) {
|
|
||||||
const char *regs[4] = { "eax", "ecx", "edx", "ebx" };
|
|
||||||
|
|
||||||
printf(" CPUID leaf: 0x%08x", instrux->CpuidFlag.Leaf);
|
|
||||||
|
|
||||||
if (instrux->CpuidFlag.SubLeaf != ND_CFF_NO_SUBLEAF)
|
|
||||||
{
|
|
||||||
printf(", sub-leaf: 0x%08x", instrux->CpuidFlag.SubLeaf);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(", reg: %s, bit %u\n", regs[instrux->CpuidFlag.Reg], instrux->CpuidFlag.Bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(" FLAGS access: ");
|
|
||||||
|
|
||||||
uint32_t all = instrux->FlagsAccess.Tested.Raw | instrux->FlagsAccess.Modified.Raw | instrux->FlagsAccess.Set.Raw
|
|
||||||
| instrux->FlagsAccess.Cleared.Raw | instrux->FlagsAccess.Undefined.Raw;
|
|
||||||
const char *flags[22] = { "CF", nullptr, "PF", nullptr, "AF", nullptr, "ZF", "SF", "TF", "IF", "DF", "OF", "IOPL", nullptr, "NT", nullptr, "RF", "VM", "AC", "VIF", "VIP", "ID" };
|
|
||||||
|
|
||||||
for (uint32_t fidx = 0; fidx < 21; fidx++) {
|
|
||||||
if (flags[fidx] != nullptr) {
|
|
||||||
if (0 == (all & (1ULL << fidx))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s: ", flags[fidx]);
|
|
||||||
|
|
||||||
if (instrux->FlagsAccess.Tested.Raw & (1ULL << fidx)) {
|
|
||||||
printf("t");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->FlagsAccess.Modified.Raw & (1ULL << fidx)) {
|
|
||||||
printf("m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->FlagsAccess.Set.Raw & (1ULL << fidx)) {
|
|
||||||
printf("1");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->FlagsAccess.Cleared.Raw & (1ULL << fidx)) {
|
|
||||||
printf("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->FlagsAccess.Undefined.Raw & (1ULL << fidx)) {
|
|
||||||
printf("u");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("; ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
printf(" Valid modes: R0: %s, R1: %s, R2: %s, R3: %s, Real: %s, V8086: %s, Prot: %s, Compat: %s, Long: %s, SMM: %s, SGX: %s, TSX: %s, VMXRoot: %s, VMXNonRoot: %s\n",
|
|
||||||
instrux->ValidModes.Ring0 ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Ring1 ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Ring2 ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Ring3 ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Real ? "yes" : "no",
|
|
||||||
instrux->ValidModes.V8086 ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Protected ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Compat ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Long ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Smm ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Sgx ? "yes" : "no",
|
|
||||||
instrux->ValidModes.Tsx ? "yes" : "no",
|
|
||||||
instrux->ValidModes.VmxRoot ? "yes" : "no",
|
|
||||||
instrux->ValidModes.VmxNonRoot ? "yes" : "no");
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < instrux->OperandsCount; i++) {
|
|
||||||
printf(" Operand %d %s Type: %10s, Size: %2d, RawSize: %2d, Encoding: %s", i,
|
|
||||||
instrux->Operands[i].Access.Read && instrux->Operands[i].Access.Write ? "RW" :
|
|
||||||
instrux->Operands[i].Access.Write ? "-W" : instrux->Operands[i].Access.Read ? "R-" : "--",
|
|
||||||
op_type_to_str(instrux->Operands[i].Type).c_str(), (int)instrux->Operands[i].Size,
|
|
||||||
(int)instrux->Operands[i].RawSize, op_enc_to_str(instrux->Operands[i].Encoding).c_str());
|
|
||||||
|
|
||||||
if (ND_OP_MEM == instrux->Operands[i].Type) {
|
|
||||||
printf(", ");
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Info.Memory.IsAG) {
|
|
||||||
printf("Address Generator, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Info.Memory.IsBitbase) {
|
|
||||||
printf("Bitbase Addressing, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Info.Memory.IsMib) {
|
|
||||||
printf("MIB Addressing, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Info.Memory.IsVsib) {
|
|
||||||
printf("VSIB Addressing, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Info.Memory.IsStack) {
|
|
||||||
printf("Stack, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Info.Memory.IsShadowStack) {
|
|
||||||
printf("Shadow Stack, ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ND_OP_REG == instrux->Operands[i].Type) {
|
|
||||||
printf(", RegType: %16s, RegSize: %2u, ",
|
|
||||||
reg_type_to_str(instrux->Operands[i].Info.Register.Type).c_str(),
|
|
||||||
instrux->Operands[i].Info.Register.Size);
|
|
||||||
if (instrux->Operands[i].Info.Register.Type == ND_REG_MSR)
|
|
||||||
{
|
|
||||||
printf("RegId: 0x%08x, RegCount: %u\n",
|
|
||||||
instrux->Operands[i].Info.Register.Reg,
|
|
||||||
instrux->Operands[i].Info.Register.Count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("RegId: %u, RegCount: %u\n",
|
|
||||||
instrux->Operands[i].Info.Register.Reg,
|
|
||||||
instrux->Operands[i].Info.Register.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Decorator.HasBroadcast) {
|
|
||||||
printf(" Decorator: Broadcast %d bytes element %d times\n",
|
|
||||||
instrux->Operands[i].Decorator.Broadcast.Size,
|
|
||||||
instrux->Operands[i].Decorator.Broadcast.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Decorator.HasMask) {
|
|
||||||
printf(" Decorator: Mask k%d\n", instrux->Operands[i].Decorator.Mask.Msk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instrux->Operands[i].Decorator.HasZero) {
|
|
||||||
printf(" Decorator: Zero (no merging)\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StringBuffer disassemble_one(uint8_t *bytes, size_t size, size_t rip, uint8_t bits, uint8_t vendor /* = ND_VEND_INTEL */)
|
|
||||||
{
|
|
||||||
INSTRUX instrux;
|
|
||||||
|
|
||||||
auto status = NdDecodeEx2(&instrux, bytes, size, bits, bits, bits, vendor);
|
|
||||||
if (!ND_SUCCESS(status))
|
|
||||||
return byte_to_json(bytes[0], rip);
|
|
||||||
else
|
|
||||||
return instrux_to_json(&instrux, rip);
|
|
||||||
}
|
|
||||||
|
|
||||||
void shemu_log(PCHAR msg)
|
|
||||||
{
|
|
||||||
printf("%s", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
ND_BOOL shemu_access_mem(void * /* Ctx */, uint64_t /* Gla */, size_t Size, uint8_t *Buffer, ND_BOOL Store)
|
|
||||||
{
|
|
||||||
if (!Store)
|
|
||||||
{
|
|
||||||
memset(Buffer, 0, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ND_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shemu(options &opts)
|
|
||||||
{
|
|
||||||
SHEMU_CONTEXT ctx = { };
|
|
||||||
SHEMU_STATUS shstatus;
|
|
||||||
|
|
||||||
auto stack = std::make_unique<uint8_t[]>(STACK_SIZE);
|
|
||||||
auto intbuf = std::make_unique<uint8_t[]>(opts.actual_size + STACK_SIZE);
|
|
||||||
auto shellcode = std::make_unique<uint8_t[]>(opts.actual_size);
|
|
||||||
|
|
||||||
ctx.Stack = stack.get();
|
|
||||||
memset(ctx.Stack, 0, STACK_SIZE);
|
|
||||||
|
|
||||||
ctx.Intbuf = intbuf.get();
|
|
||||||
memset(ctx.Intbuf, 0, opts.actual_size + STACK_SIZE);
|
|
||||||
|
|
||||||
ctx.Shellcode = shellcode.get();
|
|
||||||
memcpy(ctx.Shellcode, opts.bytes.get(), opts.actual_size);
|
|
||||||
|
|
||||||
ctx.ShellcodeSize = opts.actual_size;
|
|
||||||
ctx.StackSize = STACK_SIZE;
|
|
||||||
ctx.Registers.RegRsp = 0x101000;
|
|
||||||
ctx.IntbufSize = opts.actual_size + STACK_SIZE;
|
|
||||||
|
|
||||||
ctx.Registers.RegFlags = NDR_RFLAG_IF | 2;
|
|
||||||
ctx.Registers.RegRip = opts.rip ? opts.rip : 0x200000;
|
|
||||||
ctx.Segments.Cs.Selector = 0x10;
|
|
||||||
ctx.Segments.Ds.Selector = 0x28;
|
|
||||||
ctx.Segments.Es.Selector = 0x28;
|
|
||||||
ctx.Segments.Ss.Selector = 0x28;
|
|
||||||
ctx.Segments.Fs.Selector = 0x30;
|
|
||||||
ctx.Segments.Fs.Base = 0x7FFF0000;
|
|
||||||
ctx.Segments.Gs.Selector = 0x30;
|
|
||||||
ctx.Segments.Gs.Base = 0x7FFF0000;
|
|
||||||
|
|
||||||
// Dummy values, to resemble regular CR0/CR4 values.
|
|
||||||
ctx.Registers.RegCr0 = 0x0000000080050031;
|
|
||||||
ctx.Registers.RegCr4 = 0x0000000000170678;
|
|
||||||
|
|
||||||
ctx.Mode = opts.bits;
|
|
||||||
ctx.Ring = opts.kernel ? 0 : 3;
|
|
||||||
ctx.TibBase = (opts.bits == ND_DATA_32 ? ctx.Segments.Fs.Base : ctx.Segments.Gs.Base);
|
|
||||||
ctx.MaxInstructionsCount = 4096;
|
|
||||||
ctx.Options = SHEMU_OPT_TRACE_EMULATION;
|
|
||||||
ctx.Log = shemu_log;
|
|
||||||
ctx.AccessMemory = shemu_access_mem;
|
|
||||||
|
|
||||||
uint32_t eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
eax = ebx = ecx = edx = 0;
|
|
||||||
|
|
||||||
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
||||||
|
|
||||||
if (!!(ecx & (1UL << 25)))
|
|
||||||
{
|
|
||||||
ctx.Options |= SHEMU_OPT_SUPPORT_AES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configurable thresholds.
|
|
||||||
ctx.NopThreshold = SHEMU_DEFAULT_NOP_THRESHOLD;
|
|
||||||
ctx.StrThreshold = SHEMU_DEFAULT_STR_THRESHOLD;
|
|
||||||
ctx.MemThreshold = SHEMU_DEFAULT_MEM_THRESHOLD;
|
|
||||||
|
|
||||||
bool update_rsp = false;
|
|
||||||
|
|
||||||
if (!opts.shctx.empty() && !regs_from_json(opts.shctx, ctx.Registers, update_rsp)) {
|
|
||||||
std::cerr << "Failed to parse context file." << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consider the stack base at least with a page before the current RSP. In case of pushes or operations
|
|
||||||
// which decrease the RSP, we will always give SHEMU_ABORT_BRANCH_OUTSIDE otherwise.
|
|
||||||
ctx.StackBase = ctx.Registers.RegRsp - 0x1000;
|
|
||||||
ctx.ShellcodeBase = (ctx.Registers.RegRip ? ctx.Registers.RegRip & PAGE_MASK : 0x200000);
|
|
||||||
|
|
||||||
shstatus = ShemuEmulate(&ctx);
|
|
||||||
|
|
||||||
printf("Emulation terminated with status 0x%08x, flags: 0x%llx, %u NOPs\n",
|
|
||||||
shstatus, (unsigned long long)ctx.Flags, ctx.NopCount);
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_NOP_SLED)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_NOP_SLED\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_LOAD_RIP)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_LOAD_RIP\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_WRITE_SELF)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_WRITE_SELF\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_TIB_ACCESS)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_TIB_ACCESS\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_SYSCALL)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_SYSCALL\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_STACK_STR)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_STACK_STR\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_KPCR_ACCESS)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_KPCR_ACCESS\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_SWAPGS)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_SWAPGS\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_SYSCALL_MSR_READ)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_SYSCALL_MSR_READ\n");
|
|
||||||
}
|
|
||||||
if (ctx.Flags & SHEMU_FLAG_SYSCALL_MSR_WRITE)
|
|
||||||
{
|
|
||||||
printf(" SHEMU_FLAG_SYSCALL_MSR_WRITE\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opts.shdec_file.empty()) {
|
|
||||||
auto f = std::ofstream(opts.shdec_file, std::ios::out | std::ios::binary);
|
|
||||||
|
|
||||||
if (!f.is_open())
|
|
||||||
std::cerr << "Failed to open file " << opts.shdec_file<< std::endl;
|
|
||||||
else
|
|
||||||
f.write(reinterpret_cast<char*>(ctx.Shellcode), ctx.ShellcodeSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t disassemble(options &opts)
|
|
||||||
{
|
|
||||||
struct timespec start;
|
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start);
|
|
||||||
|
|
||||||
size_t icount = 0, miss_count = 0, ibytes = 0;
|
|
||||||
size_t rel_rip = opts.offset;
|
|
||||||
size_t total_disasm = 0;
|
|
||||||
auto bytes = opts.bytes.get();
|
|
||||||
auto disasm_size = std::min(opts.actual_size - opts.offset, opts.size);
|
|
||||||
|
|
||||||
opts.address_size = int(std::ceil(((8 * sizeof(opts.actual_size)) - __builtin_clzll(opts.actual_size)) / 4.0));
|
|
||||||
|
|
||||||
while ((total_disasm < disasm_size) && (icount < opts.count)) {
|
|
||||||
INSTRUX instrux;
|
|
||||||
|
|
||||||
auto status = NdDecodeEx2(&instrux,
|
|
||||||
&bytes[rel_rip],
|
|
||||||
opts.actual_size - rel_rip,
|
|
||||||
opts.bits,
|
|
||||||
opts.bits,
|
|
||||||
opts.bits,
|
|
||||||
opts.vendor);
|
|
||||||
|
|
||||||
if (!ND_SUCCESS(status)) {
|
|
||||||
if (!opts.dump_stats) {
|
|
||||||
|
|
||||||
if (opts.json_output) {
|
|
||||||
auto j = byte_to_json(bytes[rel_rip], rel_rip + opts.rip);
|
|
||||||
std::cout << j.GetString() << std::endl;
|
|
||||||
} else {
|
|
||||||
printf("%*zx ", opts.address_size, rel_rip + opts.rip);
|
|
||||||
printf("%02x", bytes[rel_rip]);
|
|
||||||
printf("%s", gSpaces[16 - opts.address_size]);
|
|
||||||
printf("db 0x%02x\n", bytes[rel_rip]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rel_rip++;
|
|
||||||
total_disasm++;
|
|
||||||
|
|
||||||
miss_count++;
|
|
||||||
} else {
|
|
||||||
icount++;
|
|
||||||
ibytes += instrux.Length;
|
|
||||||
|
|
||||||
if (!opts.dump_stats) {
|
|
||||||
if (opts.json_output) {
|
|
||||||
auto j = instrux_to_json(&instrux, rel_rip + opts.rip);
|
|
||||||
std::cout << j.GetString() << std::endl;
|
|
||||||
} else
|
|
||||||
print_instruction(rel_rip + opts.rip, &instrux, opts);
|
|
||||||
} else if (opts.json_output)
|
|
||||||
instrux_to_json(&instrux, rel_rip + opts.rip);
|
|
||||||
|
|
||||||
rel_rip += instrux.Length;
|
|
||||||
total_disasm += instrux.Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timespec end;
|
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
|
|
||||||
|
|
||||||
if (opts.dump_stats)
|
|
||||||
{
|
|
||||||
auto result = diff_time(end, start);
|
|
||||||
|
|
||||||
long total_ns = result.tv_sec * NSEC_PER_SEC + result.tv_nsec;
|
|
||||||
|
|
||||||
printf("Disassembled %zu instructions took %ld.%09ld seconds, %lu ns / instr.\n",
|
|
||||||
icount, result.tv_sec, result.tv_nsec, total_ns / icount);
|
|
||||||
printf("Invalid: %zu/%zu (%.2f) bytes\n", miss_count, ibytes,
|
|
||||||
(static_cast<double>(miss_count) / static_cast<double>(disasm_size)) * 100.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.rip += rel_rip;
|
|
||||||
|
|
||||||
return icount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool _validate_and_fix_args(options& opts)
|
|
||||||
{
|
|
||||||
if (!opts.interactive && !opts.comm) {
|
|
||||||
int total = 0;
|
|
||||||
|
|
||||||
if (!opts.hex_string.empty())
|
|
||||||
total++;
|
|
||||||
|
|
||||||
if (!opts.hex_file.empty())
|
|
||||||
total++;
|
|
||||||
|
|
||||||
if (!opts.in_file.empty())
|
|
||||||
total++;
|
|
||||||
|
|
||||||
if (total == 0) {
|
|
||||||
std::cerr << "Give hex, file or hex-file..." << std::endl;
|
|
||||||
return false;
|
|
||||||
} else if (total > 1) {
|
|
||||||
std::cerr << "Only one of hex, file or hex-file can be present..." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.interactive || opts.comm) {
|
|
||||||
if (!opts.in_file.empty() || !opts.hex_string.empty() || !opts.hex_file.empty()) {
|
|
||||||
std::cerr << "Interactive mode doesn't work with file, hex-string or hex-file" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.size || opts.count || opts.offset) {
|
|
||||||
std::cerr << "Interactive mode doesn't work with size, count or offset" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (opts.bits) {
|
|
||||||
case 64:
|
|
||||||
opts.bits = ND_DATA_64;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 32:
|
|
||||||
opts.bits = ND_DATA_32;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 16:
|
|
||||||
opts.bits = ND_DATA_16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
std::cerr << "Please give --bits [64,32,16]" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == opts.size)
|
|
||||||
opts.size = std::numeric_limits<std::size_t>::max();
|
|
||||||
|
|
||||||
if (0 == opts.count)
|
|
||||||
opts.count = std::numeric_limits<std::size_t>::max();
|
|
||||||
|
|
||||||
if (!isatty(fileno(stdout)))
|
|
||||||
opts.output_redirected = true;
|
|
||||||
|
|
||||||
if (!opts.hex_file.empty())
|
|
||||||
opts.shdec_file = opts.hex_file + "_decoded.bin";
|
|
||||||
else if (!opts.in_file.empty())
|
|
||||||
opts.shdec_file = opts.in_file + "_decoded.bin";
|
|
||||||
else
|
|
||||||
opts.shdec_file = "hex_string_decoded.bin";
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static size_t _get_hex_opt(argparse::ArgumentParser &parser, const std::string &field)
|
|
||||||
{
|
|
||||||
return std::strtoul(parser.get<std::string>(field).c_str(), nullptr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
auto opts = options{};
|
|
||||||
|
|
||||||
auto parser = argparse::ArgumentParser(argv[0], "Disassembler tool for Linux");
|
|
||||||
|
|
||||||
parser.add_argument("-i", "--interactive", "Interactive mode", false);
|
|
||||||
parser.add_argument("-c", "--comm", "Comm mode", false);
|
|
||||||
parser.add_argument("-r", "--rip", "Use this rip to disassemble", false);
|
|
||||||
parser.add_argument("-f", "--file", "Use this input file", false);
|
|
||||||
parser.add_argument("-x", "--hex", "Use this hex-string", false);
|
|
||||||
parser.add_argument("--hexfile", "Use this input file as a hex-string", false);
|
|
||||||
parser.add_argument("--no-color", "Don't use colors", false);
|
|
||||||
parser.add_argument("--offset", "Use this offset in file/hex-string", false);
|
|
||||||
parser.add_argument("--size", "Only disasemble this size from file/hex-string", false);
|
|
||||||
parser.add_argument("--count", "Only disasemble this many instructions", false);
|
|
||||||
parser.add_argument("--stats", "Dump statistics (time, count, etc.)", false);
|
|
||||||
parser.add_argument("-b", "--bits", "Use the arch [16, 32, 64]", false);
|
|
||||||
parser.add_argument("--verbose", "Verbose mode", false);
|
|
||||||
parser.add_argument("--json", "Output to json", false);
|
|
||||||
parser.add_argument("--extended", "Extended instruction info", false);
|
|
||||||
parser.add_argument("--shemu", "Emulate the input hexfile", false);
|
|
||||||
parser.add_argument("--kernel", "Kernel mode for shemu context", false);
|
|
||||||
parser.add_argument("--shctx", "Shemu context file. Must be a JSON file.", false);
|
|
||||||
|
|
||||||
parser.enable_help();
|
|
||||||
|
|
||||||
auto err = parser.parse(argc, argv);
|
|
||||||
if (err) {
|
|
||||||
std::cout << err << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser.exists("help")) {
|
|
||||||
parser.print_help();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.bits = parser.get<uint64_t>("bits");
|
|
||||||
opts.interactive = parser.exists("interactive");
|
|
||||||
opts.comm = parser.exists("comm");
|
|
||||||
opts.offset = _get_hex_opt(parser, "offset");
|
|
||||||
opts.size = _get_hex_opt(parser, "size");
|
|
||||||
opts.count = _get_hex_opt(parser, "count");
|
|
||||||
opts.rip = _get_hex_opt(parser, "rip");
|
|
||||||
opts.in_file = parser.get<std::string>("file");
|
|
||||||
opts.hex_string = parser.get<std::string>("hex");
|
|
||||||
opts.hex_file = parser.get<std::string>("hexfile");
|
|
||||||
opts.no_color = parser.exists("no-color");
|
|
||||||
opts.dump_stats = parser.exists("stats");
|
|
||||||
opts.verbose = parser.exists("verbose");
|
|
||||||
opts.json_output = parser.exists("json");
|
|
||||||
opts.extended = parser.exists("extended");
|
|
||||||
opts.shemu = parser.exists("shemu");
|
|
||||||
opts.kernel = parser.exists("kernel");
|
|
||||||
opts.shctx_file = parser.get<std::string>("shctx");
|
|
||||||
|
|
||||||
if (opts.verbose) {
|
|
||||||
std::cout << "interactive: " << opts.interactive << std::endl;
|
|
||||||
std::cout << "comm: " << opts.comm << std::endl;
|
|
||||||
std::cout << "rip: " << opts.rip << std::endl;
|
|
||||||
std::cout << "bits: " << static_cast<uint16_t>(opts.bits) << std::endl;
|
|
||||||
std::cout << "offset: " << opts.offset << std::endl;
|
|
||||||
std::cout << "size: " << opts.offset << std::endl;
|
|
||||||
std::cout << "count: " << opts.count << std::endl;
|
|
||||||
std::cout << "in_file: " << opts.in_file << std::endl;
|
|
||||||
std::cout << "no-color: " << opts.no_color << std::endl;
|
|
||||||
std::cout << "stats: " << opts.dump_stats << std::endl;
|
|
||||||
std::cout << "hex: " << opts.hex_string << std::endl;
|
|
||||||
std::cout << "json: " << opts.json_output << std::endl;
|
|
||||||
std::cout << "extended: " << opts.extended << std::endl;
|
|
||||||
std::cout << "shemu:" << opts.shemu << std::endl;
|
|
||||||
std::cout << "kernel:" << opts.kernel << std::endl;
|
|
||||||
std::cout << "shctx:" << opts.shctx_file << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_validate_and_fix_args(opts)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opts.interactive && !opts.comm) {
|
|
||||||
if (!opts.hex_string.empty() || !opts.hex_file.empty()) {
|
|
||||||
if (!_hexstring_to_bytes(opts))
|
|
||||||
return 1;
|
|
||||||
} else if (!opts.in_file.empty()) {
|
|
||||||
if (!_file_to_bytes(opts))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.offset >= opts.actual_size)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!opts.shemu) {
|
|
||||||
disassemble(opts);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_load_shctx(opts);
|
|
||||||
shemu(opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
while (true) {
|
|
||||||
opts.hex_string.clear();
|
|
||||||
|
|
||||||
if (!opts.comm)
|
|
||||||
std::cout << ">> ";
|
|
||||||
|
|
||||||
std::getline(std::cin, opts.hex_string);
|
|
||||||
|
|
||||||
if (opts.hex_string == "q"
|
|
||||||
|| opts.hex_string == "quit"
|
|
||||||
|| opts.hex_string == "exit"
|
|
||||||
|| opts.hex_string.empty()) {
|
|
||||||
|
|
||||||
if (!opts.comm)
|
|
||||||
std::cout << "Bye!" << std::endl;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_hexstring_to_bytes(opts);
|
|
||||||
|
|
||||||
disassemble(opts);
|
|
||||||
|
|
||||||
std::cout.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
566
disasmtool_lix/external/argparse.h
vendored
566
disasmtool_lix/external/argparse.h
vendored
@ -1,566 +0,0 @@
|
|||||||
/**
|
|
||||||
* License: Apache 2.0 with LLVM Exception or GPL v3
|
|
||||||
*
|
|
||||||
* Author: Jesse Laning
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ARGPARSE_H
|
|
||||||
#define ARGPARSE_H
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <locale>
|
|
||||||
#include <map>
|
|
||||||
#include <numeric>
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace argparse {
|
|
||||||
namespace detail {
|
|
||||||
static inline bool _not_space(int ch) { return !std::isspace(ch); }
|
|
||||||
static inline void _ltrim(std::string &s, bool (*f)(int) = _not_space) {
|
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), f));
|
|
||||||
}
|
|
||||||
static inline void _rtrim(std::string &s, bool (*f)(int) = _not_space) {
|
|
||||||
s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end());
|
|
||||||
}
|
|
||||||
static inline void _trim(std::string &s, bool (*f)(int) = _not_space) {
|
|
||||||
_ltrim(s, f);
|
|
||||||
_rtrim(s, f);
|
|
||||||
}
|
|
||||||
static inline std::string _ltrim_copy(std::string s,
|
|
||||||
bool (*f)(int) = _not_space) {
|
|
||||||
_ltrim(s, f);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
static inline std::string _rtrim_copy(std::string s,
|
|
||||||
bool (*f)(int) = _not_space) {
|
|
||||||
_rtrim(s, f);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
static inline std::string _trim_copy(std::string s,
|
|
||||||
bool (*f)(int) = _not_space) {
|
|
||||||
_trim(s, f);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
template <typename InputIt>
|
|
||||||
static inline std::string _join(InputIt begin, InputIt end,
|
|
||||||
const std::string &separator = " ") {
|
|
||||||
std::ostringstream ss;
|
|
||||||
if (begin != end) {
|
|
||||||
ss << *begin++;
|
|
||||||
}
|
|
||||||
while (begin != end) {
|
|
||||||
ss << separator;
|
|
||||||
ss << *begin++;
|
|
||||||
}
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
static inline bool _is_number(const std::string &arg) {
|
|
||||||
std::istringstream iss(arg);
|
|
||||||
float f;
|
|
||||||
iss >> std::noskipws >> f;
|
|
||||||
return iss.eof() && !iss.fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int _find_equal(const std::string &s) {
|
|
||||||
for (size_t i = 0; i < s.length(); ++i) {
|
|
||||||
// if find graph symbol before equal, end search
|
|
||||||
// i.e. don't accept --asd)f=0 arguments
|
|
||||||
// but allow --asd_f and --asd-f arguments
|
|
||||||
if (std::ispunct(static_cast<int>(s[i]))) {
|
|
||||||
if (s[i] == '=') {
|
|
||||||
return static_cast<int>(i);
|
|
||||||
} else if (s[i] == '_' || s[i] == '-') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t _find_name_end(const std::string &s) {
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < s.length(); ++i) {
|
|
||||||
if (std::ispunct(static_cast<int>(s[i]))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace is_vector_impl {
|
|
||||||
template <typename T>
|
|
||||||
struct is_vector : std::false_type {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct is_vector<std::vector<Args...>> : std::true_type {};
|
|
||||||
} // namespace is_vector_impl
|
|
||||||
|
|
||||||
// type trait to utilize the implementation type traits as well as decay the
|
|
||||||
// type
|
|
||||||
template <typename T>
|
|
||||||
struct is_vector {
|
|
||||||
static constexpr bool const value =
|
|
||||||
is_vector_impl::is_vector<typename std::decay<T>::type>::value;
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
class ArgumentParser {
|
|
||||||
private:
|
|
||||||
public:
|
|
||||||
class Argument;
|
|
||||||
|
|
||||||
class Result {
|
|
||||||
public:
|
|
||||||
Result() {}
|
|
||||||
Result(std::string err) noexcept : _error(true), _what(err) {}
|
|
||||||
|
|
||||||
operator bool() const { return _error; }
|
|
||||||
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const Result &dt);
|
|
||||||
|
|
||||||
const std::string &what() const { return _what; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _error{false};
|
|
||||||
std::string _what{};
|
|
||||||
};
|
|
||||||
|
|
||||||
class Argument {
|
|
||||||
public:
|
|
||||||
enum Position : int { LAST = -1, DONT_CARE = -2 };
|
|
||||||
enum Count : int { ANY = -1 };
|
|
||||||
|
|
||||||
Argument &name(const std::string &name) {
|
|
||||||
_names.push_back(name);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &names(std::vector<std::string> names) {
|
|
||||||
_names.insert(_names.end(), names.begin(), names.end());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &description(const std::string &description) {
|
|
||||||
_desc = description;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &required(bool req) {
|
|
||||||
_required = req;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &position(int position) {
|
|
||||||
if (position != Position::LAST) {
|
|
||||||
// position + 1 because technically argument zero is the name of the
|
|
||||||
// executable
|
|
||||||
_position = position + 1;
|
|
||||||
} else {
|
|
||||||
_position = position;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &count(int count) {
|
|
||||||
_count = count;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found() const { return _found; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<detail::is_vector<T>::value, T>::type get() {
|
|
||||||
T t = T();
|
|
||||||
typename T::value_type vt;
|
|
||||||
for (auto &s : _values) {
|
|
||||||
std::istringstream in(s);
|
|
||||||
in >> vt;
|
|
||||||
t.push_back(vt);
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<!detail::is_vector<T>::value, T>::type get() {
|
|
||||||
std::istringstream in(get<std::string>());
|
|
||||||
T t = T();
|
|
||||||
in >> t >> std::ws;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Argument(const std::string &name, const std::string &desc,
|
|
||||||
bool required = false)
|
|
||||||
: _desc(desc), _required(required) {
|
|
||||||
_names.push_back(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument() {}
|
|
||||||
|
|
||||||
friend class ArgumentParser;
|
|
||||||
int _position{Position::DONT_CARE};
|
|
||||||
int _count{Count::ANY};
|
|
||||||
std::vector<std::string> _names{};
|
|
||||||
std::string _desc{};
|
|
||||||
bool _found{false};
|
|
||||||
bool _required{false};
|
|
||||||
int _index{-1};
|
|
||||||
|
|
||||||
std::vector<std::string> _values{};
|
|
||||||
};
|
|
||||||
|
|
||||||
ArgumentParser(const std::string &bin, const std::string &desc)
|
|
||||||
: _bin(bin), _desc(desc) {}
|
|
||||||
|
|
||||||
Argument &add_argument() {
|
|
||||||
_arguments.push_back({});
|
|
||||||
_arguments.back()._index = static_cast<int>(_arguments.size()) - 1;
|
|
||||||
return _arguments.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &add_argument(const std::string &name, const std::string &long_name,
|
|
||||||
const std::string &desc, const bool required = false) {
|
|
||||||
_arguments.push_back(Argument(name, desc, required));
|
|
||||||
_arguments.back()._names.push_back(long_name);
|
|
||||||
_arguments.back()._index = static_cast<int>(_arguments.size()) - 1;
|
|
||||||
return _arguments.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
Argument &add_argument(const std::string &name, const std::string &desc,
|
|
||||||
const bool required = false) {
|
|
||||||
_arguments.push_back(Argument(name, desc, required));
|
|
||||||
_arguments.back()._index = static_cast<int>(_arguments.size()) - 1;
|
|
||||||
return _arguments.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_help(size_t count = 0, size_t page = 0) {
|
|
||||||
if (page * count > _arguments.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (page == 0) {
|
|
||||||
std::cout << "Usage: " << _bin;
|
|
||||||
if (_positional_arguments.empty()) {
|
|
||||||
std::cout << " [options...]" << std::endl;
|
|
||||||
} else {
|
|
||||||
int current = 1;
|
|
||||||
for (auto &v : _positional_arguments) {
|
|
||||||
if (v.first != Argument::Position::LAST) {
|
|
||||||
for (; current < v.first; current++) {
|
|
||||||
std::cout << " [" << current << "]";
|
|
||||||
}
|
|
||||||
std::cout
|
|
||||||
<< " ["
|
|
||||||
<< detail::_ltrim_copy(
|
|
||||||
_arguments[static_cast<size_t>(v.second)]._names[0],
|
|
||||||
[](int c) -> bool { return c != static_cast<int>('-'); })
|
|
||||||
<< "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto it = _positional_arguments.find(Argument::Position::LAST);
|
|
||||||
if (it == _positional_arguments.end()) {
|
|
||||||
std::cout << " [options...]";
|
|
||||||
} else {
|
|
||||||
std::cout
|
|
||||||
<< " [options...] ["
|
|
||||||
<< detail::_ltrim_copy(
|
|
||||||
_arguments[static_cast<size_t>(it->second)]._names[0],
|
|
||||||
[](int c) -> bool { return c != static_cast<int>('-'); })
|
|
||||||
<< "]";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
std::cout << "Options:" << std::endl;
|
|
||||||
}
|
|
||||||
if (count == 0) {
|
|
||||||
page = 0;
|
|
||||||
count = _arguments.size();
|
|
||||||
}
|
|
||||||
for (size_t i = page * count;
|
|
||||||
i < std::min<size_t>(page * count + count, _arguments.size()); i++) {
|
|
||||||
Argument &a = _arguments[i];
|
|
||||||
std::string name = a._names[0];
|
|
||||||
for (size_t n = 1; n < a._names.size(); ++n) {
|
|
||||||
name.append(", " + a._names[n]);
|
|
||||||
}
|
|
||||||
std::cout << " " << std::setw(23) << std::left << name << std::setw(23)
|
|
||||||
<< a._desc;
|
|
||||||
if (a._required) {
|
|
||||||
std::cout << " (Required)";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result parse(int argc, const char *argv[]) {
|
|
||||||
Result err;
|
|
||||||
if (argc > 1) {
|
|
||||||
// build name map
|
|
||||||
for (auto &a : _arguments) {
|
|
||||||
for (auto &n : a._names) {
|
|
||||||
std::string name = detail::_ltrim_copy(
|
|
||||||
n, [](int c) -> bool { return c != static_cast<int>('-'); });
|
|
||||||
if (_name_map.find(name) != _name_map.end()) {
|
|
||||||
return Result("Duplicate of argument name: " + n);
|
|
||||||
}
|
|
||||||
_name_map[name] = a._index;
|
|
||||||
}
|
|
||||||
if (a._position >= 0 || a._position == Argument::Position::LAST) {
|
|
||||||
_positional_arguments[a._position] = a._index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse
|
|
||||||
std::string current_arg;
|
|
||||||
size_t arg_len;
|
|
||||||
for (int argv_index = 1; argv_index < argc; ++argv_index) {
|
|
||||||
current_arg = std::string(argv[argv_index]);
|
|
||||||
arg_len = current_arg.length();
|
|
||||||
if (arg_len == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_help_enabled && (current_arg == "-h" || current_arg == "--help")) {
|
|
||||||
_arguments[static_cast<size_t>(_name_map["help"])]._found = true;
|
|
||||||
} else if (argv_index == argc - 1 &&
|
|
||||||
_positional_arguments.find(Argument::Position::LAST) !=
|
|
||||||
_positional_arguments.end()) {
|
|
||||||
err = _end_argument();
|
|
||||||
Result b = err;
|
|
||||||
err = _add_value(current_arg, Argument::Position::LAST);
|
|
||||||
if (b) {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
} else if (arg_len >= 2 &&
|
|
||||||
!detail::_is_number(current_arg)) { // ignores the case if
|
|
||||||
// the arg is just a -
|
|
||||||
// look for -a (short) or --arg (long) args
|
|
||||||
if (current_arg[0] == '-') {
|
|
||||||
err = _end_argument();
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
// look for --arg (long) args
|
|
||||||
if (current_arg[1] == '-') {
|
|
||||||
err = _begin_argument(current_arg.substr(2), true, argv_index);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
} else { // short args
|
|
||||||
err = _begin_argument(current_arg.substr(1), false, argv_index);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // argument value
|
|
||||||
err = _add_value(current_arg, argv_index);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // argument value
|
|
||||||
err = _add_value(current_arg, argv_index);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_help_enabled && exists("help")) {
|
|
||||||
return Result();
|
|
||||||
}
|
|
||||||
err = _end_argument();
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
for (auto &p : _positional_arguments) {
|
|
||||||
Argument &a = _arguments[static_cast<size_t>(p.second)];
|
|
||||||
if (a._values.size() > 0 && a._values[0][0] == '-') {
|
|
||||||
std::string name = detail::_ltrim_copy(a._values[0], [](int c) -> bool {
|
|
||||||
return c != static_cast<int>('-');
|
|
||||||
});
|
|
||||||
if (_name_map.find(name) != _name_map.end()) {
|
|
||||||
if (a._position == Argument::Position::LAST) {
|
|
||||||
return Result(
|
|
||||||
"Poisitional argument expected at the end, but argument " +
|
|
||||||
a._values[0] + " found instead");
|
|
||||||
} else {
|
|
||||||
return Result("Poisitional argument expected in position " +
|
|
||||||
std::to_string(a._position) + ", but argument " +
|
|
||||||
a._values[0] + " found instead");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto &a : _arguments) {
|
|
||||||
if (a._required && !a._found) {
|
|
||||||
return Result("Required argument not found: " + a._names[0]);
|
|
||||||
}
|
|
||||||
if (a._position >= 0 && argc >= a._position && !a._found) {
|
|
||||||
return Result("Argument " + a._names[0] + " expected in position " +
|
|
||||||
std::to_string(a._position));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
void enable_help() {
|
|
||||||
add_argument("-h", "--help", "Shows this page", false);
|
|
||||||
_help_enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool exists(const std::string &name) const {
|
|
||||||
std::string n = detail::_ltrim_copy(
|
|
||||||
name, [](int c) -> bool { return c != static_cast<int>('-'); });
|
|
||||||
auto it = _name_map.find(n);
|
|
||||||
if (it != _name_map.end()) {
|
|
||||||
return _arguments[static_cast<size_t>(it->second)]._found;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T get(const std::string &name) {
|
|
||||||
auto t = _name_map.find(name);
|
|
||||||
if (t != _name_map.end()) {
|
|
||||||
return _arguments[static_cast<size_t>(t->second)].get<T>();
|
|
||||||
}
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Result _begin_argument(const std::string &arg, bool longarg, int position) {
|
|
||||||
auto it = _positional_arguments.find(position);
|
|
||||||
if (it != _positional_arguments.end()) {
|
|
||||||
Result err = _end_argument();
|
|
||||||
Argument &a = _arguments[static_cast<size_t>(it->second)];
|
|
||||||
a._values.push_back((longarg ? "--" : "-") + arg);
|
|
||||||
a._found = true;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (_current != -1) {
|
|
||||||
return Result("Current argument left open");
|
|
||||||
}
|
|
||||||
size_t name_end = detail::_find_name_end(arg);
|
|
||||||
std::string arg_name = arg.substr(0, name_end);
|
|
||||||
if (longarg) {
|
|
||||||
int equal_pos = detail::_find_equal(arg);
|
|
||||||
auto nmf = _name_map.find(arg_name);
|
|
||||||
if (nmf == _name_map.end()) {
|
|
||||||
return Result("Unrecognized command line option '" + arg_name + "'");
|
|
||||||
}
|
|
||||||
_current = nmf->second;
|
|
||||||
_arguments[static_cast<size_t>(nmf->second)]._found = true;
|
|
||||||
if (equal_pos == 0 ||
|
|
||||||
(equal_pos < 0 &&
|
|
||||||
arg_name.length() < arg.length())) { // malformed argument
|
|
||||||
return Result("Malformed argument: " + arg);
|
|
||||||
} else if (equal_pos > 0) {
|
|
||||||
std::string arg_value = arg.substr(name_end + 1);
|
|
||||||
_add_value(arg_value, position);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Result r;
|
|
||||||
if (arg_name.length() == 1) {
|
|
||||||
return _begin_argument(arg, true, position);
|
|
||||||
} else {
|
|
||||||
for (char &c : arg_name) {
|
|
||||||
r = _begin_argument(std::string(1, c), true, position);
|
|
||||||
if (r) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
r = _end_argument();
|
|
||||||
if (r) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result _add_value(const std::string &value, int location) {
|
|
||||||
if (_current >= 0) {
|
|
||||||
Result err;
|
|
||||||
Argument &a = _arguments[static_cast<size_t>(_current)];
|
|
||||||
if (a._count >= 0 && static_cast<int>(a._values.size()) >= a._count) {
|
|
||||||
err = _end_argument();
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
goto unnamed;
|
|
||||||
}
|
|
||||||
a._values.push_back(value);
|
|
||||||
if (a._count >= 0 && static_cast<int>(a._values.size()) >= a._count) {
|
|
||||||
err = _end_argument();
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result();
|
|
||||||
} else {
|
|
||||||
unnamed:
|
|
||||||
auto it = _positional_arguments.find(location);
|
|
||||||
if (it != _positional_arguments.end()) {
|
|
||||||
Argument &a = _arguments[static_cast<size_t>(it->second)];
|
|
||||||
a._values.push_back(value);
|
|
||||||
a._found = true;
|
|
||||||
}
|
|
||||||
// TODO
|
|
||||||
return Result();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result _end_argument() {
|
|
||||||
if (_current >= 0) {
|
|
||||||
Argument &a = _arguments[static_cast<size_t>(_current)];
|
|
||||||
_current = -1;
|
|
||||||
if (static_cast<int>(a._values.size()) < a._count) {
|
|
||||||
return Result("Too few arguments given for " + a._names[0]);
|
|
||||||
}
|
|
||||||
if (a._count >= 0) {
|
|
||||||
if (static_cast<int>(a._values.size()) > a._count) {
|
|
||||||
return Result("Too many arguments given for " + a._names[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _help_enabled{false};
|
|
||||||
int _current{-1};
|
|
||||||
std::string _bin{};
|
|
||||||
std::string _desc{};
|
|
||||||
std::vector<Argument> _arguments{};
|
|
||||||
std::map<int, int> _positional_arguments{};
|
|
||||||
std::map<std::string, int> _name_map{};
|
|
||||||
};
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const ArgumentParser::Result &r) {
|
|
||||||
os << r.what();
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
inline std::string ArgumentParser::Argument::get<std::string>() {
|
|
||||||
return detail::_join(_values.begin(), _values.end());
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
inline std::vector<std::string>
|
|
||||||
ArgumentParser::Argument::get<std::vector<std::string>>() {
|
|
||||||
return _values;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace argparse
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
1662
inc/bddisasm.h
1662
inc/bddisasm.h
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,8 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#ifndef DISASMSTATUS_H
|
#ifndef BDDISASM_STATUS_H
|
||||||
#define DISASMSTATUS_H
|
#define BDDISASM_STATUS_H
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return statuses.
|
// Return statuses.
|
||||||
@ -48,6 +48,7 @@ typedef ND_UINT32 NDSTATUS;
|
|||||||
#define ND_STATUS_SIBMEM_WITHOUT_SIB 0x80000042 // Instruction uses SIBMEM, but SIB is not present.
|
#define ND_STATUS_SIBMEM_WITHOUT_SIB 0x80000042 // Instruction uses SIBMEM, but SIB is not present.
|
||||||
#define ND_STATUS_INVALID_TILE_REGS 0x80000043 // Tile registers are not unique.
|
#define ND_STATUS_INVALID_TILE_REGS 0x80000043 // Tile registers are not unique.
|
||||||
#define ND_STATUS_INVALID_DEST_REGS 0x80000044 // Destination register is not unique (used as src).
|
#define ND_STATUS_INVALID_DEST_REGS 0x80000044 // Destination register is not unique (used as src).
|
||||||
|
#define ND_STATUS_INVALID_EVEX_BYTE3 0x80000045 // EVEX payload byte 3 is invalid.
|
||||||
|
|
||||||
|
|
||||||
// Not encoding specific.
|
// Not encoding specific.
|
||||||
@ -60,4 +61,4 @@ typedef ND_UINT32 NDSTATUS;
|
|||||||
|
|
||||||
#define ND_SUCCESS(status) (status < 0x80000000)
|
#define ND_SUCCESS(status) (status < 0x80000000)
|
||||||
|
|
||||||
#endif
|
#endif // BDDISASM_STATUS_H
|
@ -2,8 +2,8 @@
|
|||||||
* Copyright (c) 2020 Bitdefender
|
* Copyright (c) 2020 Bitdefender
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#ifndef DISASM_TYPES_H
|
#ifndef BDDISASM_TYPES_H
|
||||||
#define DISASM_TYPES_H
|
#define BDDISASM_TYPES_H
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__ICC) || defined(__INTEL_COMPILER)
|
#if defined(_MSC_VER) || defined(__ICC) || defined(__INTEL_COMPILER)
|
||||||
@ -58,14 +58,17 @@ typedef int64_t ND_SINT64;
|
|||||||
#elif defined(_M_IX86) || defined(__i386__)
|
#elif defined(_M_IX86) || defined(__i386__)
|
||||||
|
|
||||||
#define ND_ARCH_X86
|
#define ND_ARCH_X86
|
||||||
|
#define ND_ARCH_IA32
|
||||||
|
|
||||||
#elif defined(_M_ARM64) || defined(__aarch64__)
|
#elif defined(_M_ARM64) || defined(__aarch64__)
|
||||||
|
|
||||||
#define ND_ARCH_AARCH64
|
#define ND_ARCH_AARCH64
|
||||||
|
#define ND_ARCH_A64
|
||||||
|
|
||||||
#elif defined(_M_ARM) || defined(__arm__)
|
#elif defined(_M_ARM) || defined(__arm__)
|
||||||
|
|
||||||
#define ND_ARCH_ARM
|
#define ND_ARCH_ARM
|
||||||
|
#define ND_ARCH_A32
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -75,11 +78,11 @@ typedef int64_t ND_SINT64;
|
|||||||
|
|
||||||
|
|
||||||
// Handle architecture definitions.
|
// Handle architecture definitions.
|
||||||
#if defined(ND_ARCH_X64) || defined(ND_ARCH_AARCH64)
|
#if defined(ND_ARCH_X64) || defined(ND_ARCH_A64)
|
||||||
|
|
||||||
typedef ND_UINT64 ND_SIZET;
|
typedef ND_UINT64 ND_SIZET;
|
||||||
|
|
||||||
#elif defined(ND_ARCH_X86) || defined(ND_ARCH_ARM)
|
#elif defined(ND_ARCH_X86) || defined(ND_ARCH_A32)
|
||||||
|
|
||||||
typedef ND_UINT32 ND_SIZET;
|
typedef ND_UINT32 ND_SIZET;
|
||||||
|
|
||||||
@ -93,8 +96,23 @@ typedef ND_UINT32 ND_SIZET;
|
|||||||
// Common definitions.
|
// Common definitions.
|
||||||
typedef ND_UINT8 ND_BOOL;
|
typedef ND_UINT8 ND_BOOL;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#define ND_NULL nullptr
|
||||||
|
#else
|
||||||
#define ND_NULL ((void *)(0))
|
#define ND_NULL ((void *)(0))
|
||||||
|
#endif
|
||||||
#define ND_TRUE (1)
|
#define ND_TRUE (1)
|
||||||
#define ND_FALSE (0)
|
#define ND_FALSE (0)
|
||||||
|
|
||||||
|
|
||||||
|
// Static assertion.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// When used without include <assert.h>, automatically maps to _Static_assert. Using static_assert is prefered, as
|
||||||
|
// it works on both C and C++.
|
||||||
|
#define ND_STATIC_ASSERT static_assert
|
||||||
|
#else
|
||||||
|
// Reserved keyword. MSVC only recognizes this if you include <assert.h>.
|
||||||
|
#define ND_STATIC_ASSERT _Static_assert
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // BDDISASM_TYPES_H
|
16
inc/bddisasm_version.h
Normal file
16
inc/bddisasm_version.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Bitdefender
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef BDDISASM_VERSION_H
|
||||||
|
#define BDDISASM_VERSION_H
|
||||||
|
|
||||||
|
#define DISASM_VERSION_MAJOR 2
|
||||||
|
#define DISASM_VERSION_MINOR 1
|
||||||
|
#define DISASM_VERSION_REVISION 0
|
||||||
|
|
||||||
|
#define SHEMU_VERSION_MAJOR DISASM_VERSION_MAJOR
|
||||||
|
#define SHEMU_VERSION_MINOR DISASM_VERSION_MINOR
|
||||||
|
#define SHEMU_VERSION_REVISION DISASM_VERSION_REVISION
|
||||||
|
|
||||||
|
#endif // BDDISASM_VERSION_H
|
427
inc/bdshemu.h
427
inc/bdshemu.h
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "bddisasm.h"
|
#include "bddisasm.h"
|
||||||
|
#include "bdshemu_x86.h"
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -14,7 +15,8 @@
|
|||||||
//
|
//
|
||||||
typedef void
|
typedef void
|
||||||
(*ShemuPrint)(
|
(*ShemuPrint)(
|
||||||
char *Data // Data to be printed.
|
char *Data, // Data to be printed.
|
||||||
|
void *Context // Optional, caller-defined, context.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -37,82 +39,18 @@ typedef ND_BOOL
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Percent of emulated instructions that must be NOP to consider a NOP sled is present.
|
typedef enum _SHEMU_ARCH_TYPE
|
||||||
#define SHEMU_DEFAULT_NOP_THRESHOLD 75
|
|
||||||
// Consecutive printable characters on stack to consider a stack string access.
|
|
||||||
#define SHEMU_DEFAULT_STR_THRESHOLD 8
|
|
||||||
// Will not emulate more than this number of external memory accesses. Once this threshold is exceeded, any external
|
|
||||||
// access will abort the emulation.
|
|
||||||
#define SHEMU_DEFAULT_MEM_THRESHOLD 0
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// General purpose registers.
|
|
||||||
//
|
|
||||||
typedef struct _SHEMU_GPR_REGS
|
|
||||||
{
|
{
|
||||||
ND_UINT64 RegRax;
|
SHEMU_ARCH_TYPE_NONE = 0,
|
||||||
ND_UINT64 RegRcx;
|
|
||||||
ND_UINT64 RegRdx;
|
// X86 includes both IA-32 and x86-64.
|
||||||
ND_UINT64 RegRbx;
|
// All SHEMU flags are supported.
|
||||||
ND_UINT64 RegRsp;
|
SHEMU_ARCH_TYPE_X86,
|
||||||
ND_UINT64 RegRbp;
|
|
||||||
ND_UINT64 RegRsi;
|
} SHEMU_ARCH_TYPE;
|
||||||
ND_UINT64 RegRdi;
|
|
||||||
ND_UINT64 RegR8;
|
|
||||||
ND_UINT64 RegR9;
|
|
||||||
ND_UINT64 RegR10;
|
|
||||||
ND_UINT64 RegR11;
|
|
||||||
ND_UINT64 RegR12;
|
|
||||||
ND_UINT64 RegR13;
|
|
||||||
ND_UINT64 RegR14;
|
|
||||||
ND_UINT64 RegR15;
|
|
||||||
ND_UINT64 RegCr2;
|
|
||||||
ND_UINT64 RegFlags;
|
|
||||||
ND_UINT64 RegDr7;
|
|
||||||
ND_UINT64 RegRip;
|
|
||||||
ND_UINT64 RegCr0;
|
|
||||||
ND_UINT64 RegCr4;
|
|
||||||
ND_UINT64 RegCr3;
|
|
||||||
ND_UINT64 RegCr8;
|
|
||||||
ND_UINT64 RegIdtBase;
|
|
||||||
ND_UINT64 RegIdtLimit;
|
|
||||||
ND_UINT64 RegGdtBase;
|
|
||||||
ND_UINT64 RegGdtLimit;
|
|
||||||
ND_UINT64 FpuRip;
|
|
||||||
} SHEMU_GPR_REGS, *PSHEMU_GPR_REGS;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
typedef struct _SHEMU_X86_CTX
|
||||||
// Segment register (with its hidden part).
|
|
||||||
//
|
|
||||||
typedef struct _SHEMU_SEG
|
|
||||||
{
|
|
||||||
ND_UINT64 Base;
|
|
||||||
ND_UINT64 Limit;
|
|
||||||
ND_UINT64 Selector;
|
|
||||||
ND_UINT64 AccessRights;
|
|
||||||
} SHEMU_SEG, *PSHEMU_SEG;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// The segment registers.
|
|
||||||
//
|
|
||||||
typedef struct _SHEMU_SEG_REGS
|
|
||||||
{
|
|
||||||
SHEMU_SEG Es;
|
|
||||||
SHEMU_SEG Cs;
|
|
||||||
SHEMU_SEG Ss;
|
|
||||||
SHEMU_SEG Ds;
|
|
||||||
SHEMU_SEG Fs;
|
|
||||||
SHEMU_SEG Gs;
|
|
||||||
} SHEMU_SEG_REGS, *PSHEMU_SEG_REGS;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Emulation context. All of these fields must be provided as input, although most of them can be 0.
|
|
||||||
//
|
|
||||||
typedef struct _SHEMU_CONTEXT
|
|
||||||
{
|
{
|
||||||
// Current instruction. Doesn't have to be provided; it always contains the currently emulated instruction.
|
// Current instruction. Doesn't have to be provided; it always contains the currently emulated instruction.
|
||||||
// When #ShemuEmulate returns, this will contain the last emulated instruction. In case of an emulation failure,
|
// When #ShemuEmulate returns, this will contain the last emulated instruction. In case of an emulation failure,
|
||||||
@ -120,10 +58,10 @@ typedef struct _SHEMU_CONTEXT
|
|||||||
INSTRUX Instruction;
|
INSTRUX Instruction;
|
||||||
|
|
||||||
// General purpose registers state. On input, the initial state. Will be updated after each emulated instruction.
|
// General purpose registers state. On input, the initial state. Will be updated after each emulated instruction.
|
||||||
SHEMU_GPR_REGS Registers;
|
SHEMU_X86_GPR_REGS Registers;
|
||||||
|
|
||||||
// Segment registers state. On input, the initial state. May be updated after some instructions.
|
// Segment registers state. On input, the initial state. May be updated after some instructions.
|
||||||
SHEMU_SEG_REGS Segments;
|
SHEMU_X86_SEG_REGS Segments;
|
||||||
|
|
||||||
// MMX register state. 8 x 8 bytes = 64 bytes for the MMX registers. Can be provided on input, if needed.
|
// MMX register state. 8 x 8 bytes = 64 bytes for the MMX registers. Can be provided on input, if needed.
|
||||||
ND_UINT64 MmxRegisters[ND_MAX_MMX_REGS];
|
ND_UINT64 MmxRegisters[ND_MAX_MMX_REGS];
|
||||||
@ -133,7 +71,7 @@ typedef struct _SHEMU_CONTEXT
|
|||||||
|
|
||||||
// General purpose registers write bitmap. After the first write, a register will be marked dirty in here.
|
// General purpose registers write bitmap. After the first write, a register will be marked dirty in here.
|
||||||
// Should be 0 on input.
|
// Should be 0 on input.
|
||||||
ND_UINT16 DirtyGprBitmap;
|
ND_UINT8 GprTracker[ND_MAX_GPR_REGS];
|
||||||
|
|
||||||
// Operating mode (ND_CODE_16, ND_CODE_32 or ND_CODE_64). Must be provided as input.
|
// Operating mode (ND_CODE_16, ND_CODE_32 or ND_CODE_64). Must be provided as input.
|
||||||
ND_UINT8 Mode;
|
ND_UINT8 Mode;
|
||||||
@ -141,11 +79,75 @@ typedef struct _SHEMU_CONTEXT
|
|||||||
// Operating ring (0, 1, 2, 3). Must be provided as input.
|
// Operating ring (0, 1, 2, 3). Must be provided as input.
|
||||||
ND_UINT8 Ring;
|
ND_UINT8 Ring;
|
||||||
|
|
||||||
// The suspicious code to be emulated. Must be provided as input.
|
} SHEMU_X86_CTX;
|
||||||
|
|
||||||
|
|
||||||
|
#define SHEMU_ICACHE_SIZE 0x100
|
||||||
|
|
||||||
|
typedef struct SHEMU_ICACHE
|
||||||
|
{
|
||||||
|
// Instruction cache.
|
||||||
|
ND_UINT8 Icache[SHEMU_ICACHE_SIZE];
|
||||||
|
|
||||||
|
// The first address that is cached.
|
||||||
|
ND_UINT64 Address;
|
||||||
|
|
||||||
|
// Number of valid bytes inside the cache. Maximum SHEMU_ICACHE_SIZE.
|
||||||
|
ND_UINT64 Size;
|
||||||
|
} SHEMU_ICACHE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct SHEMU_LOOP_TRACK
|
||||||
|
{
|
||||||
|
// The address of the loop instruction. The loop instruction can be any taken conditional or unconditional
|
||||||
|
// branch that goes backwards.
|
||||||
|
ND_UINT64 Address;
|
||||||
|
|
||||||
|
// The target of the loop instructions (the first instruction of the loop).
|
||||||
|
ND_UINT64 Target;
|
||||||
|
|
||||||
|
// The current iteration number.
|
||||||
|
ND_UINT64 Iteration;
|
||||||
|
|
||||||
|
// ND_TRUE whether tracking is active, and we are inside a loop.
|
||||||
|
ND_BOOL Active;
|
||||||
|
|
||||||
|
} SHEMU_LOOP_TRACK;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Emulation context. All of these fields must be provided as input, although most of them can be 0.
|
||||||
|
//
|
||||||
|
typedef struct _SHEMU_CONTEXT
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
// Used when ArchType is SHEMU_ARCH_TYPE_X86.
|
||||||
|
SHEMU_X86_CTX X86;
|
||||||
|
|
||||||
|
} Arch;
|
||||||
|
|
||||||
|
// Indicates architecture mode. Must be provided as input.
|
||||||
|
SHEMU_ARCH_TYPE ArchType;
|
||||||
|
|
||||||
|
// Instruction cache. Note that this caches instruction bytes, not decoded instructions.
|
||||||
|
SHEMU_ICACHE Icache;
|
||||||
|
|
||||||
|
// Tracks emulated loops.
|
||||||
|
SHEMU_LOOP_TRACK LoopTrack;
|
||||||
|
|
||||||
|
// The suspicious code to be emulated. Must be provided as input, as follows:
|
||||||
|
// - This buffer must be allocated by the caller, and it must be writeable. It should NOT point to process memory,
|
||||||
|
// as it will be modified by shemu in case of self-modifying code.
|
||||||
|
// - However, if the SHEMU_OPT_DIRECT_MAPPED_SHELL option is used, this field can point directly to process memory,
|
||||||
|
// but the AccessShellcode callback must also be provided. In this case, the buffer will NOT be modified by
|
||||||
|
// shemu.
|
||||||
ND_UINT8 *Shellcode;
|
ND_UINT8 *Shellcode;
|
||||||
|
|
||||||
// Virtual stack. RSP will point somewhere inside. Must be allocated as input, and it can be initialized with
|
// Virtual stack. RSP will point somewhere inside. Must be allocated as input, and it can be initialized with
|
||||||
// actual stack contents. Can also be 0-filled.
|
// actual stack contents. Can also be 0-filled.
|
||||||
|
// This buffer must be allocated by the caller, and it must be writeable. It should not point to process memory,
|
||||||
|
// as it will be modified by shemu.
|
||||||
ND_UINT8 *Stack;
|
ND_UINT8 *Stack;
|
||||||
|
|
||||||
// Internal use. Must be at least the size of the shell + stack. Needs not be initialized, but must be allocated
|
// Internal use. Must be at least the size of the shell + stack. Needs not be initialized, but must be allocated
|
||||||
@ -155,55 +157,69 @@ typedef struct _SHEMU_CONTEXT
|
|||||||
// Shellcode base address (the address the shellcode would see). Must be provided as input.
|
// Shellcode base address (the address the shellcode would see). Must be provided as input.
|
||||||
ND_UINT64 ShellcodeBase;
|
ND_UINT64 ShellcodeBase;
|
||||||
|
|
||||||
// Stack base address (the RSP the shellcode would see). Must be provided as input.
|
// Stack base address (the stack the shellcode would see). Must be provided as input.
|
||||||
ND_UINT64 StackBase;
|
ND_UINT64 StackBase;
|
||||||
|
|
||||||
// Shellcode size. Must be provided as input. Usually just a page in size, but can be larger.
|
// Shellcode size. Must be provided as input. Usually just a page in size, but can be larger.
|
||||||
ND_UINT32 ShellcodeSize;
|
ND_UINT64 ShellcodeSize;
|
||||||
|
|
||||||
// Stack size. Must be provided as input. Minimum two pages.
|
// Stack size. Must be provided as input. Minimum two pages.
|
||||||
ND_UINT32 StackSize;
|
ND_UINT64 StackSize;
|
||||||
|
|
||||||
// Internal buffer size. Must be provided as input. Must be at least the size of the shell + stack.
|
// Internal buffer size. Must be provided as input. Must be at least the size of the shell + stack.
|
||||||
ND_UINT32 IntbufSize;
|
ND_UINT64 IntbufSize;
|
||||||
|
|
||||||
// Number of NOPs encountered. Should be 0 on input.
|
// Number of consecutive NOPs encountered at the beginning of the code. Should be 0 on input.
|
||||||
ND_UINT32 NopCount;
|
ND_UINT64 NopCount;
|
||||||
|
|
||||||
|
// Number of '00 00' (ADD [rax], al) instructions encountered. Should be 0 on input.
|
||||||
|
ND_UINT64 NullCount;
|
||||||
|
|
||||||
// The length of the string constructed on the stack, if any. Should be 0 on input.
|
// The length of the string constructed on the stack, if any. Should be 0 on input.
|
||||||
ND_UINT32 StrLength;
|
ND_UINT64 StrLength;
|
||||||
|
|
||||||
// Number of external memory access (outside stack/shellcode). Should be 0 on input.
|
// Number of external memory access (outside stack/shellcode). Should be 0 on input.
|
||||||
ND_UINT32 ExtMemAccess;
|
ND_UINT64 ExtMemAccess;
|
||||||
|
|
||||||
// Number of emulated instructions. Should be 0 on input. Once InstructionsCount reaches MaxInstructionsCount,
|
// Number of emulated instructions. Should be 0 on input. Once InstructionsCount reaches MaxInstructionsCount,
|
||||||
// emulation will stop.
|
// emulation will stop.
|
||||||
ND_UINT32 InstructionsCount;
|
ND_UINT64 InstructionsCount;
|
||||||
|
|
||||||
|
// Number of distinct addresses executed. Will be less than or equal to InstructionsCount. In case of an infinite
|
||||||
|
// loop (JMP $), this field will be 1, but the InstructionsCount will be infinite. In case of two overlapping
|
||||||
|
// instructions, this field will be incremented twice (for example, JMP $+1).
|
||||||
|
ND_UINT64 UniqueCount;
|
||||||
|
|
||||||
// Max number of instructions that should be emulated. Once this limit has been reached, emulation will stop.
|
// Max number of instructions that should be emulated. Once this limit has been reached, emulation will stop.
|
||||||
// Lower values will mean faster processing, but less chances of detection. Higher values mean low performance,
|
// Lower values will mean faster processing, but less chances of detection. Higher values mean low performance,
|
||||||
// but very high chances of yielding useful results. Must be provided as input.
|
// but very high chances of yielding useful results. Must be provided as input.
|
||||||
ND_UINT32 MaxInstructionsCount;
|
ND_UINT64 MaxInstructionsCount;
|
||||||
|
|
||||||
// Base address of the Thread Information Block (the TIB the shellcode would normally see). Must be provided as
|
// Base address of the Thread Information Block (the TIB the shellcode would normally see). Must be provided as
|
||||||
// input.
|
// input.
|
||||||
ND_UINT64 TibBase;
|
ND_UINT64 TibBase;
|
||||||
|
|
||||||
// Shellcode Flags (see SHEMU_FLAG_*). Must be provided as input.
|
// Shellcode Flags (see SHEMU_FLAG_*). Should be 0 on input. Will be non-zero on output if a shellcode indicator
|
||||||
|
// has been met (check SHEMU_FLAG_* values for shellcode indicators).
|
||||||
|
// Note that this field should always be checked for detection. No matter the return value of the emulator,
|
||||||
|
// if this field is non-zero, a potential shellcode has been detected. This is valid even if
|
||||||
|
// SHEMU_OPT_STOP_ON_EXPLOIT is set: this option only guarantees that emulation will not continue once a shellcode
|
||||||
|
// has been encountered, but it does not guarantee that SHEMU_ABORT_SHELLCODE_DETECTED will be returned.
|
||||||
ND_UINT64 Flags;
|
ND_UINT64 Flags;
|
||||||
|
|
||||||
// Emulation options. See SHEMU_OPT_* for possible options. Must be provided as input.
|
// Emulation options. See SHEMU_OPT_* for possible options. Must be provided as input.
|
||||||
ND_UINT32 Options;
|
ND_UINT64 Options;
|
||||||
|
|
||||||
// Percent of NOPs (out of total instructions emulated) that trigger NOP sled detection. Must be provided as input.
|
// Percent of NOPs (out of total instructions emulated) that trigger NOP sled detection. Must be provided as input.
|
||||||
|
// Defaults to SHEMU_DEFAULT_NOP_THRESHOLD.
|
||||||
ND_UINT32 NopThreshold;
|
ND_UINT32 NopThreshold;
|
||||||
|
|
||||||
// Stack string length threshold. Stack-constructed strings must be at least this long to trigger stack string
|
// Stack string length threshold. Stack-constructed strings must be at least this long to trigger stack string
|
||||||
// detection. Must be provided as input.
|
// detection. Must be provided as input. Defaults to SHEMU_DEFAULT_STR_THRESHOLD.
|
||||||
ND_UINT32 StrThreshold;
|
ND_UINT32 StrThreshold;
|
||||||
|
|
||||||
// Number of external mem accesses threshold. No more than this number of external accesses will be issued. Must
|
// Number of external mem accesses threshold. No more than this number of external accesses will be issued. Must
|
||||||
// be provided as input.
|
// be provided as input. Defaults to SHEMU_DEFAULT_MEM_THRESHOLD.
|
||||||
ND_UINT32 MemThreshold;
|
ND_UINT32 MemThreshold;
|
||||||
|
|
||||||
// Optional auxiliary data, provided by the integrator. Can be NULL, or can point to integrator specific data.
|
// Optional auxiliary data, provided by the integrator. Can be NULL, or can point to integrator specific data.
|
||||||
@ -217,63 +233,223 @@ typedef struct _SHEMU_CONTEXT
|
|||||||
// If provided, will try to access additional memory. Can be NULL.
|
// If provided, will try to access additional memory. Can be NULL.
|
||||||
ShemuMemAccess AccessMemory;
|
ShemuMemAccess AccessMemory;
|
||||||
|
|
||||||
|
// Must be provided if the the SHEMU_OPT_DIRECT_MAPPED_SHELL option is used. This callback will be used to proxy
|
||||||
|
// all accesses made to the shellcode memory, including fetches, loads & stores. The AccessMemory callback is
|
||||||
|
// used only for accesses to memory that are not part of the Shellcode or the Stack.
|
||||||
|
ShemuMemAccess AccessShellcode;
|
||||||
|
|
||||||
|
// Optional context to be passed to Log. Can be NULL.
|
||||||
|
void *LogContext;
|
||||||
|
|
||||||
} SHEMU_CONTEXT, *PSHEMU_CONTEXT;
|
} SHEMU_CONTEXT, *PSHEMU_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned int SHEMU_STATUS;
|
typedef unsigned int SHEMU_STATUS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Emulation abort reasons.
|
// Emulation abort reasons.
|
||||||
//
|
//
|
||||||
#define SHEMU_SUCCESS 0 // Successfully emulated up to MaxInstructions.
|
#define SHEMU_SUCCESS 0 // Successfully emulated up to MaxInstructions.
|
||||||
#define SHEMU_ABORT_GLA_OUTSIDE 1 // Address accessed outside the shellcode or stack page.
|
#define SHEMU_ABORT_GLA_OUTSIDE 1 // A load or store outside the shellcode or the stack.
|
||||||
#define SHEMU_ABORT_BRANCH_OUTSIDE 2 // A branch outside the shellcode page.
|
#define SHEMU_ABORT_RIP_OUTSIDE 2 // A part of the instruction lies outside the shellcode.
|
||||||
#define SHEMU_ABORT_UNSUPPORTED_INSTRUX 3 // A valid but unsupported instruction was encountered.
|
#define SHEMU_ABORT_INSTRUX_NOT_SUPPORTED 3 // An unsupported instruction was encountered.
|
||||||
#define SHEMU_ABORT_INVALID_INSTRUX 4 // An invalid instruction was encountered.
|
#define SHEMU_ABORT_OPERAND_NOT_SUPPORTED 4 // An unsupported operand was encountered.
|
||||||
#define SHEMU_ABORT_ADDRESSING_UNSUPPORTED 5 // An unsupported addressing scheme used (ie, VSIB).
|
#define SHEMU_ABORT_ADDRESSING_NOT_SUPPORTED 5 // An unsupported addressing scheme used (ie, VSIB).
|
||||||
#define SHEMU_ABORT_REGISTER_NOT_SUPPORTED 6 // An unsupported register was used (ie, DR).
|
#define SHEMU_ABORT_REGISTER_NOT_SUPPORTED 6 // An unsupported register was used (ie, DR).
|
||||||
#define SHEMU_ABORT_INVALID_PARAMETER 7 // An invalid parameter was supplied.
|
#define SHEMU_ABORT_INVALID_PARAMETER 7 // An invalid parameter was supplied.
|
||||||
#define SHEMU_ABORT_OP_TOO_LARGE 8 // An operand that is too large was encountered.
|
|
||||||
#define SHEMU_ABORT_NO_PRIVILEGE 9 // A privileged instruction outside kernel mode.
|
#define SHEMU_ABORT_NO_PRIVILEGE 9 // A privileged instruction outside kernel mode.
|
||||||
#define SHEMU_ABORT_CANT_EMULATE 10 // A valid, but only partially handled instruction.
|
#define SHEMU_ABORT_CANT_EMULATE 10 // A valid, but only partially handled instruction.
|
||||||
|
#define SHEMU_ABORT_INVALID_SELECTOR 11 // An invalid selector is loaded.
|
||||||
|
#define SHEMU_ABORT_UNDEFINED 12 // Valid encoding, but undefined cominbation of bits.
|
||||||
|
#define SHEMU_ABORT_UNPREDICTABLE 13 // Instruction behavior is unpredictable.
|
||||||
|
#define SHEMU_ABORT_MISALIGNED_PC 14 // PC is not aligned to a word.
|
||||||
|
#define SHEMU_ABORT_FETCH_ERROR 15 // Could not fetch instruction bytes.
|
||||||
|
#define SHEMU_ABORT_DECODE_ERROR 16 // Could not decode the instruction.
|
||||||
|
|
||||||
#define SHEMU_ABORT_SHELLCODE_DETECTED 0xFFFFFFFF // Shellcode criteria met (see the shellcode flags).
|
#define SHEMU_ABORT_SHELLCODE_DETECTED 0xFFFFFFFF // Shellcode criteria met (see the shellcode flags).
|
||||||
|
// Note that this status may be returned if and only if
|
||||||
|
// the SHEMU_OPT_STOP_ON_EXPLOIT is used.
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum SHEMU_FLAG_ID
|
||||||
|
{
|
||||||
|
shemuFlagIdNopSled,
|
||||||
|
shemuFlagIdLoadRip,
|
||||||
|
shemuFlagIdWriteSelf,
|
||||||
|
shemuFlagIdTebAccessPeb,
|
||||||
|
shemuFlagIdSyscall,
|
||||||
|
shemuFlagIdStackStr,
|
||||||
|
shemuFlagIdTebAccessWow32,
|
||||||
|
shemuFlagIdHeavensGate,
|
||||||
|
shemuFlagIdStackPivot,
|
||||||
|
shemuFlagIdSudAccess,
|
||||||
|
|
||||||
|
// Kernel specific flags.
|
||||||
|
shemuFlagIdKpcrAccess = 32,
|
||||||
|
shemuFlagIdSwapgs,
|
||||||
|
shemuFlagIdSyscallMsrRead,
|
||||||
|
shemuFlagIdSyscallMsrWrite,
|
||||||
|
shemuFlagIdSidt,
|
||||||
|
} SHEMU_FLAG_ID;
|
||||||
|
|
||||||
|
#define SHEMU_FLAG(id) (1ull << (id))
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Shellcode flags.
|
// Shellcode flags.
|
||||||
//
|
//
|
||||||
|
|
||||||
// General and user-mode flags.
|
// General and user-mode flags.
|
||||||
#define SHEMU_FLAG_NOP_SLED 0x00000001 // Long sequence of NOP instructions.
|
|
||||||
#define SHEMU_FLAG_LOAD_RIP 0x00000002 // The code loads RIP (CALL/POP, FNSTENV/POP, etc.)
|
// Long sequence of NOP instructions. Generally present before the actual shellcode. This flag will only be set if:
|
||||||
#define SHEMU_FLAG_WRITE_SELF 0x00000004 // The code writes itself (decryption, unpacking, etc.)
|
// 1. Minimum MaxInstructions / 2 instructions have been emulated;
|
||||||
#define SHEMU_FLAG_TIB_ACCESS 0x00000008 // The code accesses the PEB field inside TIB.
|
// 2. Minimum NopThreshold fraction (percent) of the emulated instructions are NOPs;
|
||||||
#define SHEMU_FLAG_SYSCALL 0x00000010 // The code does a direct syscall/sysenter/int 0x2e|0x80.
|
// 3. No other abort condition is met during emulation.
|
||||||
#define SHEMU_FLAG_STACK_STR 0x00000020 // The code constructs & uses strings on the stack.
|
#define SHEMU_FLAG_NOP_SLED SHEMU_FLAG(shemuFlagIdNopSled)
|
||||||
#define SHEMU_FLAG_TIB_ACCESS_WOW32 0x00000040 // The code accesses the Wow32Reserved field inside TIB.
|
|
||||||
#define SHEMU_FLAG_HEAVENS_GATE 0x00000080 // The code uses Heaven's gate to switch into 64 bit mode.
|
// The code loads RIP (CALL/POP, FNSTENV/POP, etc.). Almost always used by shellcodes in order to determine their
|
||||||
#define SHEMU_FLAG_STACK_PIVOT 0x00000100 // The code switched the stack using XCHG esp, *.
|
// position in memory. This flag will be set when the value of the instruction pointer is loaded into a general
|
||||||
#define SHEMU_FLAG_SUD_ACCESS 0x00000200 // The code accesses the KUSER_SHARED_DATA page.
|
// purpose register by any means. Techniques covered include, but are not limited to:
|
||||||
|
// 1. CALL + POP reg;
|
||||||
|
// 2. FP instruction + FNSTENV + loading the saved RIP from the saved FPU state.
|
||||||
|
// Loading the RIP via RIP relative addressing on x64 does not set this flag.
|
||||||
|
#define SHEMU_FLAG_LOAD_RIP SHEMU_FLAG(shemuFlagIdLoadRip)
|
||||||
|
|
||||||
|
// The code writes itself (decryption, unpacking, etc.). Commonly seen if the shellcode decrypts itself in memory.
|
||||||
|
// This flag will only be set if previously written data is executed. This flag will not be set if, for example,
|
||||||
|
// chunks of data are written within the shellcode but never executed.
|
||||||
|
#define SHEMU_FLAG_WRITE_SELF SHEMU_FLAG(shemuFlagIdWriteSelf)
|
||||||
|
|
||||||
|
// The code accesses the PEB field inside TEB. This is achieved via "FS:[0x30]" or "GS:[0x60]" accesses. Inside
|
||||||
|
// bdshemu, accesses to the linear address inside TEB is detected no mater how obfuscated - for example, the
|
||||||
|
// following instructions will all set this flag:
|
||||||
|
// 1. MOV eax, gs:[0x30]
|
||||||
|
// 2. MOV eax, 0x30; MOV eax, fs:[eax]
|
||||||
|
// 3. MOV eax, 0; MOV eax, fs:[eax+0x30]
|
||||||
|
#define SHEMU_FLAG_TIB_ACCESS SHEMU_FLAG(shemuFlagIdTebAccessPeb)
|
||||||
|
#define SHEMU_FLAG_TIB_ACCESS_PEB SHEMU_FLAG_TIB_ACCESS
|
||||||
|
|
||||||
|
// The code does a direct syscall/sysenter/int 0x2e|0x80. This should never happen outside the legitimate ntdll
|
||||||
|
// module. However, payloads may issue direct system calls in order to avoid detection, or to simply avoid fixing
|
||||||
|
// imports manually.
|
||||||
|
// Note that this flag will be set when the SYSCALL, SYSENTER, INT 0x2E or INT 0x80 is executed, but only if
|
||||||
|
// the EAX register contains a value that resembles a valid system call (< 0x1000).
|
||||||
|
#define SHEMU_FLAG_SYSCALL SHEMU_FLAG(shemuFlagIdSyscall)
|
||||||
|
|
||||||
|
// The code constructs & uses strings on the stack. The flag will be set only if:
|
||||||
|
// 1. The length of the string constructed on the stack is at least StrThreshold bytes long (default 8);
|
||||||
|
// 2. The constructed string is referenced by loading its address anywhere (including a register or memory).
|
||||||
|
#define SHEMU_FLAG_STACK_STR SHEMU_FLAG(shemuFlagIdStackStr)
|
||||||
|
|
||||||
|
// The code accesses the Wow32Reserved field inside TIB. This is generally used to issue system calls from Wow64.
|
||||||
|
#define SHEMU_FLAG_TIB_ACCESS_WOW32 SHEMU_FLAG(shemuFlagIdTebAccessWow32)
|
||||||
|
|
||||||
|
// The code uses Heaven's gate to switch into 64 bit mode. This can be abused by shellcodes in order to avoid
|
||||||
|
// detection by switching from legacy 32 bit mode to 64 bit mode.
|
||||||
|
#define SHEMU_FLAG_HEAVENS_GATE SHEMU_FLAG(shemuFlagIdHeavensGate)
|
||||||
|
|
||||||
|
// The code switches the stack using XCHG esp, *. This is commonly executed by a shellcode once it receives
|
||||||
|
// control after a stack pivot. By itself, this flag is FP prone, and should generally not be used alone.
|
||||||
|
// This flag will only be set if several conditions are met:
|
||||||
|
// 1. The XCHG instruction is used to load a new value in the RSP register
|
||||||
|
// 2. The new value is naturally aligned (8 bytes in 64-bit mode, 4 bytes in 32-bit mode)
|
||||||
|
// 3. The new value points either inside the shellcode or the stack area, and at least 64 bytes are valid
|
||||||
|
#define SHEMU_FLAG_STACK_PIVOT SHEMU_FLAG(shemuFlagIdStackPivot)
|
||||||
|
|
||||||
|
// The code accesses the KUSER_SHARED_DATA page. Commonly used by shellcodes which wish to issue direct system
|
||||||
|
// cals or to access various data located inside the SharedUserData page. Only accesses to the following fields
|
||||||
|
// will set this flag:
|
||||||
|
// 1. KdDebuggerEnabled (offset 0x2D4)
|
||||||
|
// 2. SystemCall (offset 0x308)
|
||||||
|
// 3. Cookie (offset 0x300)
|
||||||
|
#define SHEMU_FLAG_SUD_ACCESS SHEMU_FLAG(shemuFlagIdSudAccess)
|
||||||
|
|
||||||
|
|
||||||
// Kernel specific flags.
|
// Kernel specific flags.
|
||||||
#define SHEMU_FLAG_KPCR_ACCESS 0x00010000 // KPCR current thread access via gs:[0x188]/fs:[0x124].
|
|
||||||
#define SHEMU_FLAG_SWAPGS 0x00020000 // SWAPGS was executed.
|
// KPCR current thread access via gs:[0x188]/fs:[0x124]. Commonly used by kernel shellcodes in order to get the
|
||||||
#define SHEMU_FLAG_SYSCALL_MSR_READ 0x00040000 // A SYSCALL/SYSENTER MSR read.
|
// currently exeucting thread.
|
||||||
#define SHEMU_FLAG_SYSCALL_MSR_WRITE 0x00080000 // A SYSCALL/SYSENTER MSR write.
|
#define SHEMU_FLAG_KPCR_ACCESS SHEMU_FLAG(shemuFlagIdKpcrAccess)
|
||||||
#define SHEMU_FLAG_SIDT 0x00100000 // SIDT was executed.
|
|
||||||
|
// SWAPGS was executed. Shellcodes may use this if they intercept a low-level event such as the SYSCALL.
|
||||||
|
#define SHEMU_FLAG_SWAPGS SHEMU_FLAG(shemuFlagIdSwapgs)
|
||||||
|
|
||||||
|
// A SYSCALL/SYSENTER MSR was read. Commonly used to locate the nt image in order to manually fix imports.
|
||||||
|
#define SHEMU_FLAG_SYSCALL_MSR_READ SHEMU_FLAG(shemuFlagIdSyscallMsrRead)
|
||||||
|
|
||||||
|
// A SYSCALL/SYSENTER MSR was written. Commonly used to intercept events such as SYSCALLs.
|
||||||
|
#define SHEMU_FLAG_SYSCALL_MSR_WRITE SHEMU_FLAG(shemuFlagIdSyscallMsrWrite)
|
||||||
|
|
||||||
|
// SIDT was executed. Commonly used to locate the nt image in order to manually fix imports.
|
||||||
|
#define SHEMU_FLAG_SIDT SHEMU_FLAG(shemuFlagIdSidt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Emulation thresholds.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Percent of emulated instructions that must be NOP to consider a NOP sled is present.
|
||||||
|
#define SHEMU_DEFAULT_NOP_THRESHOLD 75
|
||||||
|
|
||||||
|
// Consecutive printable characters on stack to consider a stack string access.
|
||||||
|
#define SHEMU_DEFAULT_STR_THRESHOLD 8
|
||||||
|
|
||||||
|
// Will not emulate more than this number of external memory accesses. Once this threshold is exceeded, any external
|
||||||
|
// access will abort the emulation.
|
||||||
|
#define SHEMU_DEFAULT_MEM_THRESHOLD 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Emulation options.
|
// Emulation options.
|
||||||
//
|
//
|
||||||
#define SHEMU_OPT_TRACE_EMULATION 0x00000001 // Trace each emulated instruction.
|
|
||||||
#define SHEMU_OPT_STOP_ON_EXPLOIT 0x00000002 // When shellcode indications are confirmed, stop emulation.
|
// Trace each emulated instruction.
|
||||||
#define SHEMU_OPT_BYPASS_SELF_WRITES 0x00000004 // When a shellcode self-modifies, the modification will
|
#define SHEMU_OPT_TRACE_EMULATION 0x0000000000000001
|
||||||
// not be committed. Use this when emulating an already
|
|
||||||
// decoded shellcode, where emulating the decryption again
|
// When shellcode indications are confirmed, stop emulation. Note that this flag only guarantees that emulation
|
||||||
// will in fact scramble the shellcode and make it useless.
|
// will stop once we set any flag, but it does not guarantee that SHEMU_ABORT_SHELLCODE_DETECTED will be returned,
|
||||||
#define SHEMU_OPT_SUPPORT_AES 0x00010000 // Indicates that AES instructions are supported, and
|
// as an emulation error may take place at any moment. Always check the Flags field of the SHEMU_CONTEXT structure
|
||||||
// therefore, the AES intrinsics can be used to emulate
|
// to determine whether a detection took place or not.
|
||||||
// AES decryption.
|
#define SHEMU_OPT_STOP_ON_EXPLOIT 0x0000000000000002
|
||||||
|
|
||||||
|
// When a shellcode self-modifies, the modification will not be committed. Use this when emulating an already
|
||||||
|
// decoded shellcode, where emulating the decryption again will in fact scramble the shellcode and make it useless.
|
||||||
|
#define SHEMU_OPT_BYPASS_SELF_WRITES 0x0000000000000004
|
||||||
|
|
||||||
|
// Trace each memory access.
|
||||||
|
#define SHEMU_OPT_TRACE_MEMORY 0x0000000000000008
|
||||||
|
|
||||||
|
// Trace each identified dynamically constructed string.
|
||||||
|
#define SHEMU_OPT_TRACE_STRINGS 0x0000000000000010
|
||||||
|
|
||||||
|
// Shellcode is directly mapped, and it is not read in a dedicated buffer. No stores can be done to it. This
|
||||||
|
// allows for arbitrarly sized shellcodes to be emulated without the need to allocate separate memory & do
|
||||||
|
// copied of the target shellcode. Internally, pieces of the shellcode may still be cached.
|
||||||
|
// The size of IntBuf must be equal only to the size of the stack plus one page, and no extra memory
|
||||||
|
// needs to be allocated for the shellcode. When using this flag, the following features will not be available:
|
||||||
|
// 1. UniqueCount - it will simply indicate the total number of instructions emulated, NOT the number of unique
|
||||||
|
// instructions emulated
|
||||||
|
// 2. WRITE_SELF - self-write detection will be disabled
|
||||||
|
// Other features will work normally, as they don't require state tracking inside the IntBuf.
|
||||||
|
// When using this option, the SHEMU_OPT_BYPASS_SELF_WRITES is forced as well.
|
||||||
|
#define SHEMU_OPT_DIRECT_MAPPED_SHELL 0x0000000000000020
|
||||||
|
|
||||||
|
// Trace each identified loop.
|
||||||
|
#define SHEMU_OPT_TRACE_LOOPS 0x0000000000000080
|
||||||
|
|
||||||
|
// Indicates that AES instructions are supported, and therefore, the AES intrinsics can be used to emulate
|
||||||
|
// AES decryption.
|
||||||
|
#define SHEMU_OPT_SUPPORT_AES 0x0000000100000000
|
||||||
|
// Emulate with APX support enabled. If not provided, APX and REX2 prefixed instructions will cause emulation to
|
||||||
|
// stop.
|
||||||
|
#define SHEMU_OPT_SUPPORT_APX 0x0000000200000000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -282,6 +458,8 @@ typedef unsigned int SHEMU_STATUS;
|
|||||||
#define SHEMU_INTERNAL_BUFFER_SIZE(ctx) ((ctx)->ShellcodeSize + (ctx)->StackSize)
|
#define SHEMU_INTERNAL_BUFFER_SIZE(ctx) ((ctx)->ShellcodeSize + (ctx)->StackSize)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -289,6 +467,11 @@ extern "C" {
|
|||||||
//
|
//
|
||||||
// API
|
// API
|
||||||
//
|
//
|
||||||
|
SHEMU_STATUS
|
||||||
|
ShemuX86Emulate(
|
||||||
|
SHEMU_CONTEXT *Context
|
||||||
|
);
|
||||||
|
|
||||||
SHEMU_STATUS
|
SHEMU_STATUS
|
||||||
ShemuEmulate(
|
ShemuEmulate(
|
||||||
SHEMU_CONTEXT *Context
|
SHEMU_CONTEXT *Context
|
||||||
|
92
inc/bdshemu_x86.h
Normal file
92
inc/bdshemu_x86.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Bitdefender
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef BDSHEMU_X86_
|
||||||
|
#define BDSHEMU_X86_
|
||||||
|
|
||||||
|
#include "bddisasm_types.h"
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// General purpose registers.
|
||||||
|
//
|
||||||
|
typedef struct _SHEMU_X86_GPR_REGS
|
||||||
|
{
|
||||||
|
ND_UINT64 RegRax;
|
||||||
|
ND_UINT64 RegRcx;
|
||||||
|
ND_UINT64 RegRdx;
|
||||||
|
ND_UINT64 RegRbx;
|
||||||
|
ND_UINT64 RegRsp;
|
||||||
|
ND_UINT64 RegRbp;
|
||||||
|
ND_UINT64 RegRsi;
|
||||||
|
ND_UINT64 RegRdi;
|
||||||
|
ND_UINT64 RegR8;
|
||||||
|
ND_UINT64 RegR9;
|
||||||
|
ND_UINT64 RegR10;
|
||||||
|
ND_UINT64 RegR11;
|
||||||
|
ND_UINT64 RegR12;
|
||||||
|
ND_UINT64 RegR13;
|
||||||
|
ND_UINT64 RegR14;
|
||||||
|
ND_UINT64 RegR15;
|
||||||
|
ND_UINT64 RegR16;
|
||||||
|
ND_UINT64 RegR17;
|
||||||
|
ND_UINT64 RegR18;
|
||||||
|
ND_UINT64 RegR19;
|
||||||
|
ND_UINT64 RegR20;
|
||||||
|
ND_UINT64 RegR21;
|
||||||
|
ND_UINT64 RegR22;
|
||||||
|
ND_UINT64 RegR23;
|
||||||
|
ND_UINT64 RegR24;
|
||||||
|
ND_UINT64 RegR25;
|
||||||
|
ND_UINT64 RegR26;
|
||||||
|
ND_UINT64 RegR27;
|
||||||
|
ND_UINT64 RegR28;
|
||||||
|
ND_UINT64 RegR29;
|
||||||
|
ND_UINT64 RegR30;
|
||||||
|
ND_UINT64 RegR31;
|
||||||
|
ND_UINT64 RegCr2;
|
||||||
|
ND_UINT64 RegFlags;
|
||||||
|
ND_UINT64 RegDr7;
|
||||||
|
ND_UINT64 RegRip;
|
||||||
|
ND_UINT64 RegCr0;
|
||||||
|
ND_UINT64 RegCr4;
|
||||||
|
ND_UINT64 RegCr3;
|
||||||
|
ND_UINT64 RegCr8;
|
||||||
|
ND_UINT64 RegIdtBase;
|
||||||
|
ND_UINT64 RegIdtLimit;
|
||||||
|
ND_UINT64 RegGdtBase;
|
||||||
|
ND_UINT64 RegGdtLimit;
|
||||||
|
ND_UINT64 FpuRip;
|
||||||
|
} SHEMU_X86_GPR_REGS, *PSHEMU_X86_GPR_REGS;
|
||||||
|
|
||||||
|
|
||||||
|
ND_STATIC_ASSERT(ND_MAX_GPR_REGS <= 32, "Too many General Purpose Registers defined in bddisasm! Make sure to update SHEMU_X86_GPR_REGS!");
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Segment register (with its hidden part).
|
||||||
|
//
|
||||||
|
typedef struct _SHEMU_X86_SEG
|
||||||
|
{
|
||||||
|
ND_UINT64 Base;
|
||||||
|
ND_UINT64 Limit;
|
||||||
|
ND_UINT64 Selector;
|
||||||
|
ND_UINT64 AccessRights;
|
||||||
|
} SHEMU_X86_SEG, *PSHEMU_X86_SEG;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The segment registers.
|
||||||
|
//
|
||||||
|
typedef struct _SHEMU_X86_SEG_REGS
|
||||||
|
{
|
||||||
|
SHEMU_X86_SEG Es;
|
||||||
|
SHEMU_X86_SEG Cs;
|
||||||
|
SHEMU_X86_SEG Ss;
|
||||||
|
SHEMU_X86_SEG Ds;
|
||||||
|
SHEMU_X86_SEG Fs;
|
||||||
|
SHEMU_X86_SEG Gs;
|
||||||
|
} SHEMU_X86_SEG_REGS, *PSHEMU_X86_SEG_REGS;
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user