Add test with ASAN enabled. (#2313)

* Add test with ASAN enabled.

* Fix leaks in cstool and cs.c

* Add work around so ASAN binaries don't DEADSIGNAL due to too many randomized address bits.

* Add ASAN build arguments to cstest

* Fix leaks in cstest

* Use cstest binary build by the main build.

* Add clonging step for cmocka when cstest is build

* Skip Python tests for ASAN

* Remove make build from CI

* Fix leaks in cstest.

- Rewrite split to remove leaks and improve runtime by 6%
- Add free()

* Fix cmocka external project to stable branch.

* Revert "Fix leaks in cstest."

This reverts commit bf8ee125b0c58f9c794eb081a69c80f8a71825cd.

* Fix memleaks in cstest

* Document adding of ASAN job to release guide

* Add CAPSTONE_BUILD_CSTEST to build docs

* Fix double free

* Add more detail tests to CI and fix them

* Initialize variables

* Fix typo

* Update cstest build docs

* Revert "Remove make build from CI"

This reverts commit 84f7360c6da6183cd41bec0fef3e1d0a2ee49ddf.

* Make cstest only run for cmake builds.

* Add cstest job for make build.

* Add CAPSTONE_DIET build test.

* Compile the compatibility header test with ASAN if enabled.

* Fix DIET build by excluding not used code.

* Missing "

* Build static library with ASAN and DIET if enabled.

* Revert "Add CAPSTONE_DIET build test."

This reverts commit 71e1469dee.
This commit is contained in:
Rot127 2024-06-10 02:01:00 +00:00 committed by GitHub
parent 03c41e1be4
commit 0a67596f70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 152 additions and 53 deletions

View File

@ -36,6 +36,7 @@ jobs:
python-arch: x64,
python-version: '3.6',
build-system: 'cmake',
enable-asan: 'OFF'
}
- {
name: 'ubuntu-22.04 x64 python3.9 make',
@ -44,7 +45,8 @@ jobs:
python-arch: x64,
python-version: '3.9',
build-system: 'make',
}
enable-asan: 'OFF'
}
- {
name: 'ubuntu-22.04 x64 python3.9 cmake',
os: ubuntu-22.04,
@ -52,6 +54,7 @@ jobs:
python-arch: x64,
python-version: '3.9',
build-system: 'cmake',
enable-asan: 'OFF'
}
- {
name: 'ubuntu-22.04 x64 python3.11 cmake',
@ -60,6 +63,16 @@ jobs:
python-arch: x64,
python-version: '3.11',
build-system: 'cmake',
enable-asan: 'OFF'
}
- {
name: 'ubuntu-22.04 x64 python3.11 ASAN',
os: ubuntu-latest,
arch: x64,
python-arch: x64,
python-version: '3.11',
build-system: 'cmake',
enable-asan: 'ON'
}
steps:
@ -88,35 +101,61 @@ jobs:
- name: cmake
if: startsWith(matrix.config.build-system, 'cmake')
env:
asan: ${{ matrix.config.enable-asan }}
run: |
mkdir build && cd build
# build static library
cmake -DCAPSTONE_INSTALL=1 -DCMAKE_INSTALL_PREFIX=/usr ..
cmake -DCAPSTONE_INSTALL=1 -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_ASAN=${asan} -DCAPSTONE_BUILD_DIET=${diet_build} ..
cmake --build . --config Release
# build shared library
cmake -DCAPSTONE_INSTALL=1 -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr ..
cmake -DCAPSTONE_INSTALL=1 -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr -DCAPSTONE_BUILD_CSTEST=ON -DENABLE_ASAN=${asan} ..
sudo cmake --build . --config Release --target install
cp libcapstone.* ../
cp libcapstone.* ../tests/
cp test_* ../tests/
- name: Lower number of KASL randomized address bits
run: |
# Work-around ASAN bug https://github.com/google/sanitizers/issues/1716
sudo sysctl vm.mmap_rnd_bits=28
- name: "Compatibility header test build"
if: matrix.config.diet-build == 'OFF'
env:
asan: ${{ matrix.config.enable-asan }}
run: |
cd "$(git rev-parse --show-toplevel)/suite/auto-sync/c_tests/"
clang -lcapstone src/test_arm64_compatibility_header.c -o test_arm64_compatibility_header
if [ "$asan" = "ON" ]; then
clang -lcapstone -fsanitize=address src/test_arm64_compatibility_header.c -o test_arm64_compatibility_header
else
clang -lcapstone src/test_arm64_compatibility_header.c -o test_arm64_compatibility_header
fi
./test_arm64_compatibility_header
cd "$(git rev-parse --show-toplevel)"
- name: cstool - reaches disassembler engine
run: |
sh suite/run_invalid_cstool.sh
- name: cstest
- name: cstest (cmake)
if: startsWith(matrix.config.build-system, 'cmake')
run: |
python suite/cstest/cstest_report.py -D -d suite/MC
python suite/cstest/cstest_report.py -D -f suite/cstest/issues.cs
python suite/cstest/cstest_report.py -D -f tests/cs_details/issue.cs
- name: cstest (make)
if: startsWith(matrix.config.build-system, 'make')
run: |
cd suite/cstest && ./build_cstest.sh
python cstest_report.py -D -t build/cstest -d ../MC
python cstest_report.py -D -t build/cstest -f issues.cs; cd ..
python cstest_report.py -D -t build/cstest -f issues.cs
python cstest_report.py -D -t build/cstest -f ../../tests/cs_details/issue.cs
cd ../../
- name: verify python binding
if: matrix.config.enable-asan == 'OFF'
run: |
mkdir -p bindings/python/capstone/lib && cp libcapstone.so.5.* bindings/python/capstone/lib/libcapstone.so
cd bindings/python
@ -136,6 +175,7 @@ jobs:
make check
- name: run python binding test
if: matrix.config.enable-asan == 'OFF'
run: |
cp libcapstone.* bindings/python/prebuilt
cd bindings/python
@ -144,6 +184,7 @@ jobs:
BUILD_TESTS=no make tests
- name: run cython binding test
if: matrix.config.enable-asan == 'OFF'
run: |
pip install cython
cd bindings/python

View File

@ -68,6 +68,13 @@ option(CAPSTONE_USE_ARCH_REGISTRATION "Use explicit architecture registration" O
option(CAPSTONE_ARCHITECTURE_DEFAULT "Whether architectures are enabled by default" ON)
option(CAPSTONE_DEBUG "Whether to enable extra debug assertions" OFF)
option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
option(ENABLE_ASAN "Enable address sanitizer" OFF)
if (ENABLE_ASAN)
add_definitions(-DASAN_ENABLED)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
# If building for OSX it's best to allow CMake to handle building both architectures
if(APPLE AND NOT CAPSTONE_BUILD_MACOS_THIN)
@ -855,16 +862,28 @@ if(CAPSTONE_BUILD_CSTOOL)
endif()
if(CAPSTONE_BUILD_CSTEST)
find_package(PkgConfig REQUIRED)
pkg_check_modules(CMOCKA REQUIRED IMPORTED_TARGET cmocka)
include(ExternalProject)
ExternalProject_Add(cmocka_ext
PREFIX extern
GIT_REPOSITORY "https://git.cryptomilk.org/projects/cmocka.git"
GIT_TAG "origin/stable-1.1"
CONFIGURE_COMMAND cmake -DBUILD_SHARED_LIBS=OFF ../cmocka_ext/
BUILD_COMMAND cmake --build . --config Release
INSTALL_COMMAND ""
)
set(CMOCKA_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern/src/cmocka_ext/include)
set(CMOCKA_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern/src/cmocka_ext-build/src/)
add_library(cmocka STATIC IMPORTED)
set_target_properties(cmocka PROPERTIES IMPORTED_LOCATION ${CMOCKA_LIB_DIR}/libcmocka.a)
file(GLOB CSTEST_SRC suite/cstest/src/*.c)
add_executable(cstest ${CSTEST_SRC})
target_link_libraries(cstest PUBLIC capstone PkgConfig::CMOCKA)
add_dependencies(cstest cmocka_ext)
target_link_libraries(cstest PUBLIC capstone cmocka)
target_include_directories(cstest PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
${PROJECT_SOURCE_DIR}/suite/cstest/include
${CMOCKA_INCLUDE_DIRS}
${CMOCKA_INCLUDE_DIR}
)
if(CAPSTONE_INSTALL)

View File

@ -56,6 +56,8 @@ Get CMake for free from http://www.cmake.org.
- CAPSTONE_X86_REDUCE: change this to ON to make X86 binary smaller.
- CAPSTONE_X86_ATT_DISABLE: change this to ON to disable AT&T syntax on x86.
- CAPSTONE_DEBUG: change this to ON to enable extra debug assertions.
- CAPSTONE_BUILD_CSTEST: Build `cstest` in `suite/cstest/`
- ENABLE_ASAN: Compiles Capstone with the address sanitizer.
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE
modes are disabled. To use your own memory allocations, turn ON both DIET &

View File

@ -74,17 +74,27 @@ const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
/// Macro for easier access of operand types from the map.
/// Assumes the istruction operands map is called "insn_operands"
/// Only usable by `auto-sync` archs!
#ifndef CAPSTONE_DIET
#define map_get_op_type(MI, OpNum) \
mapping_get_op_type(MI, OpNum, (const map_insn_ops *)insn_operands, \
sizeof(insn_operands) / sizeof(insn_operands[0]))
#else
#define map_get_op_type(MI, OpNum) \
CS_OP_INVALID
#endif
/// Macro for easier access of operand access flags from the map.
/// Assumes the istruction operands map is called "insn_operands"
/// Only usable by `auto-sync` archs!
#ifndef CAPSTONE_DIET
#define map_get_op_access(MI, OpNum) \
mapping_get_op_access(MI, OpNum, (const map_insn_ops *)insn_operands, \
sizeof(insn_operands) / \
sizeof(insn_operands[0]))
#else
#define map_get_op_access(MI, OpNum) \
CS_AC_INVALID
#endif
///< Map for ids to their string
typedef struct name_map {
@ -212,4 +222,4 @@ bool map_use_alias_details(const MCInst *MI);
void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_id_map, int map_size);
#endif // CS_MAPPING_H
#endif // CS_MAPPING_H

View File

@ -762,11 +762,11 @@ void ARM_init_mri(MCRegisterInfo *MRI)
ARR_SIZE(ARMSubRegIdxLists), 0);
}
#ifndef CAPSTONE_DIET
static const map_insn_ops insn_operands[] = {
#include "ARMGenCSMappingInsnOp.inc"
};
#ifndef CAPSTONE_DIET
void ARM_reg_access(const cs_insn *insn, cs_regs regs_read,
uint8_t *regs_read_count, cs_regs regs_write,
uint8_t *regs_write_count)

View File

@ -760,6 +760,7 @@ static void add_groups(MCInst *MI)
}
}
#ifndef CAPSTONE_DIET
static void update_regs_access(MCInst *MI, unsigned int opcode)
{
if (opcode == HPPA_INS_INVALID)
@ -803,6 +804,7 @@ static void update_regs_access(MCInst *MI, unsigned int opcode)
break;
}
}
#endif
void HPPA_printInst(MCInst *MI, SStream *O, void *Info)
{

View File

@ -300,6 +300,7 @@ const char *HPPA_insn_name(csh handle, unsigned int id)
#endif
}
#ifndef CAPSTONE_DIET
/* Integer register names, indexed by the numbers which appear in the
opcodes. */
static const char *const reg_names[] = {
@ -341,6 +342,7 @@ static const char *const sp_fp_reg[] = {
"fr16R", "fr17R", "fr18R", "fr19R", "fr20R", "fr21R", "fr22R", "fr23R",
"fr24R", "fr25R", "fr26R", "fr27R", "fr28R", "fr29R", "fr30R", "fr31R"
};
#endif
const char *HPPA_reg_name(csh handle, unsigned int reg)
{
@ -437,4 +439,4 @@ void HPPA_reg_access(const cs_insn *insn, cs_regs regs_read,
sort_and_uniq(regs_write, write_count, regs_write_count);
}
#endif
#endif

View File

@ -225,8 +225,10 @@ void PPC_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
MI->fillDetailOps = detail_is_set(MI);
MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
PPC_LLVM_printInst(MI, MI->address, "", O);
#ifndef CAPSTONE_DIET
map_set_alias_id(MI, O, insn_alias_mnem_map,
ARR_SIZE(insn_alias_mnem_map));
#endif
}
bool PPC_getInstruction(csh handle, const uint8_t *bytes, size_t bytes_len,
@ -264,9 +266,11 @@ bool PPC_getFeatureBits(unsigned int mode, unsigned int feature)
return true;
}
#ifndef CAPSTONE_DIET
static const map_insn_ops insn_operands[] = {
#include "PPCGenCSMappingInsnOp.inc"
};
#endif
/// @brief Handles memory operands.
/// @param MI The MCInst.

7
cs.c
View File

@ -697,7 +697,7 @@ CAPSTONE_EXPORT
cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
{
cs_err err;
struct cs_struct *ud;
struct cs_struct *ud = NULL;
if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc || !cs_mem_free || !cs_vsnprintf)
// Error: before cs_open(), dynamic memory management must be initialized
// with cs_option(CS_OPT_MEM)
@ -736,6 +736,7 @@ cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
return CS_ERR_OK;
} else {
cs_mem_free(ud);
*handle = 0;
return CS_ERR_ARCH;
}
@ -744,8 +745,8 @@ cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
CAPSTONE_EXPORT
cs_err CAPSTONE_API cs_close(csh *handle)
{
struct cs_struct *ud;
struct insn_mnem *next, *tmp;
struct cs_struct *ud = NULL;
struct insn_mnem *next = NULL, *tmp = NULL;
if (*handle == 0)
// invalid handle

View File

@ -678,13 +678,15 @@ int main(int argc, char **argv)
}
cs_free(insn, count);
free(assembly);
} else {
printf("ERROR: invalid assembly code\n");
cs_close(&handle);
free(assembly);
return(-4);
}
cs_close(&handle);
free(assembly);
return 0;
}

View File

@ -58,6 +58,8 @@ void print_insn_detail_arm(csh handle, cs_insn *ins)
printf("\t\t\toperands[%u].mem.scale: %d\n", i, op->mem.scale);
if (op->mem.disp != 0)
printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
if (op->mem.align != 0)
printf("\t\t\toperands[%u].mem.align: 0x%x\n", i, op->mem.align);
if (op->mem.lshift != 0)
printf("\t\t\toperands[%u].mem.lshift: 0x%x\n", i, op->mem.lshift);

View File

@ -174,6 +174,7 @@ These features are only supported by `auto-sync`-enabled architectures.
**More code quality checks**
- `clang-tidy` is now run on all files changed by a PR.
- ASAN: All tests are now run with the address sanitizer enabled. This includes checking for leaks.
**Instruction formats for PPC**

View File

@ -6,7 +6,7 @@ LIBRARY = -lcmocka -lcapstone -L../..
all:
rm -rf $(BUILD)
mkdir $(BUILD)
$(CC) $(SOURCE)/*.c $(INCLUDE:%=-I %) -g -o $(BUILD)/cstest $(LIBRARY)
$(CC) $(SOURCE)/*.c $(INCLUDE:%=-I %) ${CMAKE_C_FLAGS} -g -o $(BUILD)/cstest $(LIBRARY)
cstest:
$(BUILD)/cstest -d ../MC
clean:

View File

@ -13,23 +13,12 @@ brew install cmocka
- Build Cmocka
```
cd cmocka_dir
mkdir build
cd build
cmake ..
make
sudo make install
```
## Build
- Build `cstest`
You can build `cstest` with `cmake` when building Capstone. Just pass the `CAPSTONE_BUILD_CSTEST` flag
during configuration.
```
cd suite/cstest
make
```
Alternatively you can use the `build_cstest.sh` file in this directory.
## Usage

View File

@ -1,9 +1,21 @@
#!/bin/sh
#!/bin/sh -x
cd cmocka
mkdir build
cd build
cd cmocka && mkdir build && cd build
if [ "$(uname)" = Darwin ]; then
cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make -j2 && sudo make install
cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make -j2 && sudo make install
elif [ "$asan" = "ON" ]; then
CMAKE_C_FLAGS="-fsanitize=address" CMAKE_LINK_FLAGS="-fsanitize=address" cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make -j2 && sudo make install
else # Linux
cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make -j2 && sudo make install
cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make -j2 && sudo make install
fi
cd ../..
if [ "$asan" = "ON" ]; then
CMAKE_C_FLAGS="-fsanitize=address" make
else
make
fi
cd ../.. && make

View File

@ -15,7 +15,7 @@ def Usage(s):
sys.exit(-1)
def get_report_file(toolpath, filepath, getDetails, cmt_out):
cmd = [toolpath, '-f', filepath]
cmd = [toolpath if toolpath else "cstest", '-f', filepath]
process = Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
if process.returncode != 0:

View File

@ -17,7 +17,7 @@
#define X86_32 1
#define X86_64 2
char **split(char *str, char *delim, int *size);
char **split(const char *str, const char *delim, int *size);
void print_strs(char **list_str, int size);
void free_strs(char **list_str, int size);
void add_str(char **src, const char *format, ...);

View File

@ -52,6 +52,8 @@ char *get_detail_arm(csh *handle, cs_mode mode, cs_insn *ins)
add_str(&result, " ; operands[%u].mem.scale: %d", i, op->mem.scale);
if (op->mem.disp != 0)
add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp);
if (op->mem.align != 0)
add_str(&result, " ; operands[%u].mem.align: 0x%x", i, op->mem.align);
if (op->mem.lshift != 0)
add_str(&result, " ; operands[%u].mem.lshift: 0x%x", i, op->mem.lshift);

View File

@ -85,6 +85,10 @@ void test_single_MC(csh *handle, int mc_mode, char *line)
// and laeds to wrong results.
cs_arch arch = ((struct cs_struct *)(uintptr_t)*handle)->arch;
if (arch != CS_ARCH_ARM) {
if (insn->detail) {
free(insn->detail);
}
free(insn);
cs_disasm(*handle, code, size_byte, offset, 0, &insn);
strcpy(tmp_noreg, insn[0].mnemonic);
@ -232,6 +236,7 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
offset = 0;
list_byte = split(offset_opcode[0], ",", &size_byte);
}
free_strs(offset_opcode, size_offset_opcode);
code = (unsigned char *)malloc(sizeof(char) * size_byte);
for (i = 0; i < size_byte; ++i) {
@ -239,6 +244,8 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
}
count = cs_disasm(*handle, code, size_byte, offset, 0, &insn);
free_strs(list_byte, size_byte);
free(code);
for (i = 0; i < count; ++i) {
tmp = (char *)malloc(strlen(insn[i].mnemonic) + strlen(insn[i].op_str) + 100);
strcpy(tmp, insn[i].mnemonic);
@ -280,10 +287,10 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" not in \"%s\"\n", list_part[0], list_part_issue_result[i], cs_result);
cs_free(insn, count);
free_strs(list_part, size_part);
free_strs(list_byte, size_byte);
free(cs_result);
// free_strs(list_part_cs_result, size_part_cs_result);
free_strs(list_part_issue_result, size_part_issue_result);
free(tmptmp);
_fail(__FILE__, __LINE__);
}
free(tmptmp);
@ -291,7 +298,6 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
cs_free(insn, count);
free_strs(list_part, size_part);
free_strs(list_byte, size_byte);
free(cs_result);
// free_strs(list_part_cs_result, size_part_cs_result);
free_strs(list_part_issue_result, size_part_issue_result);

View File

@ -4,15 +4,12 @@
#include "helper.h"
char **split(char *str, char *delim, int *size)
char **split(const char *str, const char *delim, int *size)
{
char **result;
char *token, *src;
int cnt;
cnt = 0;
src = str;
result = NULL;
char **result = NULL;
char *token = NULL;
const char *src = str;
int cnt = 0;
while ((token = strstr(src, delim)) != NULL) {
result = (char **)realloc(result, sizeof(char *) * (cnt + 1));

View File

@ -431,6 +431,11 @@ static void test_file(const char *filename)
printf("[!] Noted:\n[ ERROR ] --- \"<capstone result>\" != \"<user result>\"\n");
printf("\n\n");
free_strs(list_lines, size_lines);
for (int k = 0; tests && k < number_of_tests; k++) {
free((char *)tests[k].name);
}
free(tests);
free(content);
}
static void test_folder(const char *folder)

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/sh -x
cstool -d x64 0x4 | grep "ERROR: invalid assembly code" &&
cstool -d arm 0x1 | grep "ERROR: invalid assembly code" &&
@ -27,3 +27,5 @@ cstool -d riscv64 0x1 | grep "ERROR: invalid assembly code" &&
cstool -d sh 0x1 | grep "ERROR: invalid assembly code" &&
cstool -d tc162 0x1 | grep "ERROR: invalid assembly code"
# One successful disassembly
cstool -d x64 0xc5,0xca,0x58,0xd4

View File

@ -130,7 +130,7 @@
!# issue 0 ARM operand groups 0xa4,0xf9,0x6d,0x0e == vld3.16 {d0[], d2[], d4[]}, [r4]! ;
!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
0xa4,0xf9,0x6d,0x0e == vld3.16 {d0[], d2[], d4[]}, [r4]! ; op_count: 4 ; operands[0].type: REG = d0 ; operands[0].access: WRITE ; operands[1].type: REG = d2 ; operands[1].access: WRITE ; operands[2].type: REG = d4 ; operands[2].access: WRITE ; operands[3].type: MEM ; operands[3].mem.index: REG = r4 ; operands[3].access: READ ; Write-back: True ; Registers read: r4 ; Registers modified: r4 d0 d2 d4
0xa4,0xf9,0x6d,0x0e == vld3.16 {d0[], d2[], d4[]}, [r4]! ; op_count: 4 ; operands[0].type: REG = d0 ; operands[0].access: WRITE ; operands[1].type: REG = d2 ; operands[1].access: WRITE ; operands[2].type: REG = d4 ; operands[2].access: WRITE ; operands[3].type: MEM ; operands[3].mem.base: REG = r4 ; operands[3].access: READ | WRITE ; Write-back: True ; Registers read: r4 ; Registers modified: r4 d0 d2 d4
!# issue 0 ARM operand groups 0x0d,0x50,0x66,0xe4 == strbt r5, [r6], #-13 ;
!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
@ -166,7 +166,7 @@
!# issue 0 ARM operand groups 0xa4,0xf9,0xed,0x0b == vld4.32 {d0[1], d2[1], d4[1], d6[1]}, [r4:128]! ;
!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL
0xa4,0xf9,0xed,0x0b == vld4.32 {d0[1], d2[1], d4[1], d6[1]}, [r4:0x80]! ; op_count: 5 ; operands[0].type: REG = d0 ; operands[0].neon_lane = 1 ; operands[0].access: READ | WRITE ; operands[1].type: REG = d2 ; operands[1].neon_lane = 1 ; operands[1].access: READ | WRITE ; operands[2].type: REG = d4 ; operands[2].neon_lane = 1 ; operands[2].access: READ | WRITE ; operands[3].type: REG = d6 ; operands[3].neon_lane = 1 ; operands[3].access: READ | WRITE ; operands[4].type: MEM ; operands[4].mem.index: REG = r4 ; operands[4].mem.disp: 0x80 ; operands[4].access: READ ; Write-back: True ; Registers read: d0 d2 d4 d6 r4 ; Registers modified: r4 d0 d2 d4 d6
0xa4,0xf9,0xed,0x0b == vld4.32 {d0[1], d2[1], d4[1], d6[1]}, [r4:0x80]! ; op_count: 5 ; operands[0].type: REG = d0 ; operands[0].neon_lane = 1 ; operands[0].access: READ | WRITE ; operands[1].type: REG = d2 ; operands[1].neon_lane = 1 ; operands[1].access: READ | WRITE ; operands[2].type: REG = d4 ; operands[2].neon_lane = 1 ; operands[2].access: READ | WRITE ; operands[3].type: REG = d6 ; operands[3].neon_lane = 1 ; operands[3].access: READ | WRITE ; operands[4].type: MEM ; operands[4].mem.base: REG = r4 ; operands[4].mem.align: 0x80 ; operands[4].access: READ | WRITE ; Write-back: True ; Registers read: d0 d2 d4 d6 r4 ; Registers modified: r4 d0 d2 d4 d6
!# issue 0 ARM operand groups 0x42,0x03,0xb0,0xf3 == aesd.8 q0, q1 ;
!# CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8, CS_OPT_DETAIL
@ -202,5 +202,5 @@
!# issue 0 ARM operand groups 0xef,0xf3,0x11,0x85 == ldrhi pc, [r1, #-0x3ef]
!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL
0xef,0xf3,0x11,0x85 == ldrhi pc, [r1, #-0x3ef] ; op_count: 2 ; operands[0].type: REG = r15 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r1 ; operands[1].mem.disp: 0x3ef ; operands[1].access: READ ; Code condition: 8 ; Registers read: cpsr r1 ; Registers modified: r15 ; Groups: IsARM
0xef,0xf3,0x11,0x85 == ldrhi pc, [r1, #-0x3ef] ; op_count: 2 ; operands[0].type: REG = r15 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r1 ; operands[1].mem.disp: 0x3ef ; operands[1].access: READ ; Code condition: 8 ; Registers read: cpsr r1 ; Registers modified: r15 ; Groups: IsARM jump